blob: 7f1641fb7d7dcb213831634825dd853fb440be65 [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
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
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
Amit Blay02eff132011-09-21 16:46:24 +0300385 if (IS_ERR(motg->phy_reset_clk))
386 return 0;
387
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530388 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
389 if (ret) {
390 dev_err(motg->otg.dev, "usb phy clk assert failed\n");
391 return ret;
392 }
393 usleep_range(10000, 12000);
394 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
395 if (ret)
396 dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
397 return ret;
398}
399
400static int msm_otg_phy_reset(struct msm_otg *motg)
401{
402 u32 val;
403 int ret;
404 int retries;
405
406 ret = msm_otg_link_clk_reset(motg, 1);
407 if (ret)
408 return ret;
409 ret = msm_otg_phy_clk_reset(motg);
410 if (ret)
411 return ret;
412 ret = msm_otg_link_clk_reset(motg, 0);
413 if (ret)
414 return ret;
415
416 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
417 writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
418
419 for (retries = 3; retries > 0; retries--) {
420 ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
421 ULPI_CLR(ULPI_FUNC_CTRL));
422 if (!ret)
423 break;
424 ret = msm_otg_phy_clk_reset(motg);
425 if (ret)
426 return ret;
427 }
428 if (!retries)
429 return -ETIMEDOUT;
430
431 /* This reset calibrates the phy, if the above write succeeded */
432 ret = msm_otg_phy_clk_reset(motg);
433 if (ret)
434 return ret;
435
436 for (retries = 3; retries > 0; retries--) {
437 ret = ulpi_read(&motg->otg, ULPI_DEBUG);
438 if (ret != -ETIMEDOUT)
439 break;
440 ret = msm_otg_phy_clk_reset(motg);
441 if (ret)
442 return ret;
443 }
444 if (!retries)
445 return -ETIMEDOUT;
446
447 dev_info(motg->otg.dev, "phy_reset: success\n");
448 return 0;
449}
450
451#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
452static int msm_otg_reset(struct otg_transceiver *otg)
453{
454 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
455 struct msm_otg_platform_data *pdata = motg->pdata;
456 int cnt = 0;
457 int ret;
458 u32 val = 0;
459 u32 ulpi_val = 0;
460
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700461 clk_enable(motg->clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530462 ret = msm_otg_phy_reset(motg);
463 if (ret) {
464 dev_err(otg->dev, "phy_reset failed\n");
465 return ret;
466 }
467
468 ulpi_init(motg);
469
470 writel(USBCMD_RESET, USB_USBCMD);
471 while (cnt < LINK_RESET_TIMEOUT_USEC) {
472 if (!(readl(USB_USBCMD) & USBCMD_RESET))
473 break;
474 udelay(1);
475 cnt++;
476 }
477 if (cnt >= LINK_RESET_TIMEOUT_USEC)
478 return -ETIMEDOUT;
479
480 /* select ULPI phy */
481 writel(0x80000000, USB_PORTSC);
482
483 msleep(100);
484
485 writel(0x0, USB_AHBBURST);
486 writel(0x00, USB_AHBMODE);
487
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700488 /* Ensure that RESET operation is completed before turning off clock */
489 mb();
490 clk_disable(motg->clk);
491
492 val = readl_relaxed(USB_OTGSC);
493 if (pdata->mode == USB_OTG) {
494 ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
495 val |= OTGSC_IDIE | OTGSC_BSVIE;
496 } else if (pdata->mode == USB_PERIPHERAL) {
497 ulpi_val = ULPI_INT_SESS_VALID;
498 val |= OTGSC_BSVIE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530499 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500 writel_relaxed(val, USB_OTGSC);
501 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
502 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
503
504 msm_chg_enable_aca_det(motg);
505 msm_chg_enable_aca_intr(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530506
507 return 0;
508}
509
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530510#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530511#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
512
513#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530514static int msm_otg_suspend(struct msm_otg *motg)
515{
516 struct otg_transceiver *otg = &motg->otg;
517 struct usb_bus *bus = otg->host;
518 struct msm_otg_platform_data *pdata = motg->pdata;
519 int cnt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700520 bool session_active;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530521
522 if (atomic_read(&motg->in_lpm))
523 return 0;
524
525 disable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700526 session_active = (otg->host && !test_bit(ID, &motg->inputs)) ||
527 test_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530528 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530529 * Chipidea 45-nm PHY suspend sequence:
530 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530531 * Interrupt Latch Register auto-clear feature is not present
532 * in all PHY versions. Latch register is clear on read type.
533 * Clear latch register to avoid spurious wakeup from
534 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530535 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530536 * PHY comparators are disabled when PHY enters into low power
537 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
538 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
539 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530540 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530541 * PLL is not turned off when PHY enters into low power mode (LPM).
542 * Disable PLL for maximum power savings.
543 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530544
545 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
546 ulpi_read(otg, 0x14);
547 if (pdata->otg_control == OTG_PHY_CONTROL)
548 ulpi_write(otg, 0x01, 0x30);
549 ulpi_write(otg, 0x08, 0x09);
550 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530551
552 /*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700553 * Turn off the OTG comparators, if depends on PMIC for
554 * VBUS and ID notifications.
555 */
556 if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !session_active) {
557 ulpi_write(otg, OTG_COMP_DISABLE,
558 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
559 motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
560 }
561
562 /*
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530563 * PHY may take some time or even fail to enter into low power
564 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
565 * in failure case.
566 */
567 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
568 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
569 if (readl(USB_PORTSC) & PORTSC_PHCD)
570 break;
571 udelay(1);
572 cnt++;
573 }
574
575 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
576 dev_err(otg->dev, "Unable to suspend PHY\n");
577 msm_otg_reset(otg);
578 enable_irq(motg->irq);
579 return -ETIMEDOUT;
580 }
581
582 /*
583 * PHY has capability to generate interrupt asynchronously in low
584 * power mode (LPM). This interrupt is level triggered. So USB IRQ
585 * line must be disabled till async interrupt enable bit is cleared
586 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
587 * block data communication from PHY.
588 */
589 writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
590
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700591 if (motg->caps & ALLOW_PHY_RETENTION && !session_active) {
592 writel_relaxed(readl_relaxed(USB_PHY_CTRL) & ~PHY_RETEN,
593 USB_PHY_CTRL);
594 motg->lpm_flags |= PHY_RETENTIONED;
595 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530596
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700597 /* Ensure that above operation is completed before turning off clocks */
598 mb();
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530599 clk_disable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530600 if (motg->core_clk)
601 clk_disable(motg->core_clk);
602
Amit Blay137575f2011-11-06 15:20:54 +0200603 if (!IS_ERR(motg->system_clk))
604 clk_disable(motg->system_clk);
605
Anji jonnala0f73cac2011-05-04 10:19:46 +0530606 if (!IS_ERR(motg->pclk_src))
607 clk_disable(motg->pclk_src);
608
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700609 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !session_active) {
610 msm_hsusb_ldo_enable(motg, 0);
611 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530612 }
613
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700614 if (motg->lpm_flags & PHY_RETENTIONED)
615 msm_hsusb_config_vddcx(0);
616
617 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530618 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619 if (motg->pdata->pmic_id_irq)
620 enable_irq_wake(motg->pdata->pmic_id_irq);
621 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530622 if (bus)
623 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
624
625 atomic_set(&motg->in_lpm, 1);
626 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700627 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530628
629 dev_info(otg->dev, "USB in low power mode\n");
630
631 return 0;
632}
633
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530634static int msm_otg_resume(struct msm_otg *motg)
635{
636 struct otg_transceiver *otg = &motg->otg;
637 struct usb_bus *bus = otg->host;
638 int cnt = 0;
639 unsigned temp;
640
641 if (!atomic_read(&motg->in_lpm))
642 return 0;
643
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700644 wake_lock(&motg->wlock);
Anji jonnala0f73cac2011-05-04 10:19:46 +0530645 if (!IS_ERR(motg->pclk_src))
646 clk_enable(motg->pclk_src);
647
Amit Blay137575f2011-11-06 15:20:54 +0200648 if (!IS_ERR(motg->system_clk))
649 clk_enable(motg->system_clk);
650
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530651 clk_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530652 if (motg->core_clk)
653 clk_enable(motg->core_clk);
654
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700655 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
656 msm_hsusb_ldo_enable(motg, 1);
657 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
658 }
659
660 if (motg->lpm_flags & PHY_RETENTIONED) {
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530661 msm_hsusb_config_vddcx(1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700662 writel_relaxed(readl_relaxed(USB_PHY_CTRL) | PHY_RETEN,
663 USB_PHY_CTRL);
664 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530665 }
666
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530667 temp = readl(USB_USBCMD);
668 temp &= ~ASYNC_INTR_CTRL;
669 temp &= ~ULPI_STP_CTRL;
670 writel(temp, USB_USBCMD);
671
672 /*
673 * PHY comes out of low power mode (LPM) in case of wakeup
674 * from asynchronous interrupt.
675 */
676 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
677 goto skip_phy_resume;
678
679 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
680 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
681 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
682 break;
683 udelay(1);
684 cnt++;
685 }
686
687 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
688 /*
689 * This is a fatal error. Reset the link and
690 * PHY. USB state can not be restored. Re-insertion
691 * of USB cable is the only way to get USB working.
692 */
693 dev_err(otg->dev, "Unable to resume USB."
694 "Re-plugin the cable\n");
695 msm_otg_reset(otg);
696 }
697
698skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700699 /* Turn on the OTG comparators on resume */
700 if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
701 ulpi_write(otg, OTG_COMP_DISABLE,
702 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
703 motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
704 }
705 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530706 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700707 if (motg->pdata->pmic_id_irq)
708 disable_irq_wake(motg->pdata->pmic_id_irq);
709 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530710 if (bus)
711 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
712
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530713 atomic_set(&motg->in_lpm, 0);
714
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530715 if (motg->async_int) {
716 motg->async_int = 0;
717 pm_runtime_put(otg->dev);
718 enable_irq(motg->irq);
719 }
720
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530721 dev_info(otg->dev, "USB exited from low power mode\n");
722
723 return 0;
724}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530725#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530726
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530727static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
728{
729 if (motg->cur_power == mA)
730 return;
731
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530732 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700733 pm8921_charger_vbus_draw(mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530734 motg->cur_power = mA;
735}
736
737static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
738{
739 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
740
741 /*
742 * Gadget driver uses set_power method to notify about the
743 * available current based on suspend/configured states.
744 *
745 * IDEV_CHG can be drawn irrespective of suspend/un-configured
746 * states when CDP/ACA is connected.
747 */
748 if (motg->chg_type == USB_SDP_CHARGER)
749 msm_otg_notify_charger(motg, mA);
750
751 return 0;
752}
753
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530754static void msm_otg_start_host(struct otg_transceiver *otg, int on)
755{
756 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
757 struct msm_otg_platform_data *pdata = motg->pdata;
758 struct usb_hcd *hcd;
759
760 if (!otg->host)
761 return;
762
763 hcd = bus_to_hcd(otg->host);
764
765 if (on) {
766 dev_dbg(otg->dev, "host on\n");
767
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530768 /*
769 * Some boards have a switch cotrolled by gpio
770 * to enable/disable internal HUB. Enable internal
771 * HUB before kicking the host.
772 */
773 if (pdata->setup_gpio)
774 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530775 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530776 } else {
777 dev_dbg(otg->dev, "host off\n");
778
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530779 usb_remove_hcd(hcd);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530780 if (pdata->setup_gpio)
781 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530782 }
783}
784
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700785static int msm_otg_usbdev_notify(struct notifier_block *self,
786 unsigned long action, void *priv)
787{
788 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
789 struct usb_device *udev;
790
791 switch (action) {
792 case USB_DEVICE_ADD:
793 case USB_DEVICE_CONFIG:
794 udev = priv;
795 /*
796 * Interested in devices connected directly to the root hub.
797 * ACA dock can supply IDEV_CHG irrespective devices connected
798 * on the accessory port.
799 */
800 if (!udev->parent || udev->parent->parent ||
801 motg->chg_type == USB_ACA_DOCK_CHARGER)
802 break;
803 if (udev->actconfig)
804 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
805 else
806 motg->mA_port = IUNIT;
807
808 if (test_bit(ID_A, &motg->inputs))
809 msm_otg_notify_charger(motg, IDEV_CHG_MIN -
810 motg->mA_port);
811 break;
812 default:
813 break;
814 }
815 return NOTIFY_OK;
816}
817
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530818static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
819{
820 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
821 struct usb_hcd *hcd;
822
823 /*
824 * Fail host registration if this board can support
825 * only peripheral configuration.
826 */
827 if (motg->pdata->mode == USB_PERIPHERAL) {
828 dev_info(otg->dev, "Host mode is not supported\n");
829 return -ENODEV;
830 }
831
832 if (!host) {
833 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530834 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700835 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530836 msm_otg_start_host(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700837 if (motg->pdata->vbus_power)
838 motg->pdata->vbus_power(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530839 otg->host = NULL;
840 otg->state = OTG_STATE_UNDEFINED;
841 schedule_work(&motg->sm_work);
842 } else {
843 otg->host = NULL;
844 }
845
846 return 0;
847 }
848
849 hcd = bus_to_hcd(host);
850 hcd->power_budget = motg->pdata->power_budget;
851
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
853 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530854 otg->host = host;
855 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
856
857 /*
858 * Kick the state machine work, if peripheral is not supported
859 * or peripheral is already registered with us.
860 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530861 if (motg->pdata->mode == USB_HOST || otg->gadget) {
862 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530863 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530864 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530865
866 return 0;
867}
868
869static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
870{
871 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
872 struct msm_otg_platform_data *pdata = motg->pdata;
873
874 if (!otg->gadget)
875 return;
876
877 if (on) {
878 dev_dbg(otg->dev, "gadget on\n");
879 /*
880 * Some boards have a switch cotrolled by gpio
881 * to enable/disable internal HUB. Disable internal
882 * HUB before kicking the gadget.
883 */
884 if (pdata->setup_gpio)
885 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
886 usb_gadget_vbus_connect(otg->gadget);
887 } else {
888 dev_dbg(otg->dev, "gadget off\n");
889 usb_gadget_vbus_disconnect(otg->gadget);
890 if (pdata->setup_gpio)
891 pdata->setup_gpio(OTG_STATE_UNDEFINED);
892 }
893
894}
895
896static int msm_otg_set_peripheral(struct otg_transceiver *otg,
897 struct usb_gadget *gadget)
898{
899 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
900
901 /*
902 * Fail peripheral registration if this board can support
903 * only host configuration.
904 */
905 if (motg->pdata->mode == USB_HOST) {
906 dev_info(otg->dev, "Peripheral mode is not supported\n");
907 return -ENODEV;
908 }
909
910 if (!gadget) {
911 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530912 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530913 msm_otg_start_peripheral(otg, 0);
914 otg->gadget = NULL;
915 otg->state = OTG_STATE_UNDEFINED;
916 schedule_work(&motg->sm_work);
917 } else {
918 otg->gadget = NULL;
919 }
920
921 return 0;
922 }
923 otg->gadget = gadget;
924 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
925
926 /*
927 * Kick the state machine work, if host is not supported
928 * or host is already registered with us.
929 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530930 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
931 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530932 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530933 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530934
935 return 0;
936}
937
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700938#ifdef CONFIG_USB_MSM_ACA
939static bool msm_chg_aca_detect(struct msm_otg *motg)
940{
941 struct otg_transceiver *otg = &motg->otg;
942 u32 int_sts;
943 bool ret = false;
944
945 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
946 goto out;
947
948 int_sts = ulpi_read(otg, 0x87);
949 switch (int_sts & 0x1C) {
950 case 0x08:
951 if (!test_and_set_bit(ID_A, &motg->inputs)) {
952 dev_dbg(otg->dev, "ID_A\n");
953 motg->chg_type = USB_ACA_A_CHARGER;
954 motg->chg_state = USB_CHG_STATE_DETECTED;
955 clear_bit(ID_B, &motg->inputs);
956 clear_bit(ID_C, &motg->inputs);
957 ret = true;
958 }
959 break;
960 case 0x0C:
961 if (!test_and_set_bit(ID_B, &motg->inputs)) {
962 dev_dbg(otg->dev, "ID_B\n");
963 motg->chg_type = USB_ACA_B_CHARGER;
964 motg->chg_state = USB_CHG_STATE_DETECTED;
965 clear_bit(ID_A, &motg->inputs);
966 clear_bit(ID_C, &motg->inputs);
967 ret = true;
968 }
969 break;
970 case 0x10:
971 if (!test_and_set_bit(ID_C, &motg->inputs)) {
972 dev_dbg(otg->dev, "ID_C\n");
973 motg->chg_type = USB_ACA_C_CHARGER;
974 motg->chg_state = USB_CHG_STATE_DETECTED;
975 clear_bit(ID_A, &motg->inputs);
976 clear_bit(ID_B, &motg->inputs);
977 ret = true;
978 }
979 break;
980 default:
981 ret = test_and_clear_bit(ID_A, &motg->inputs) |
982 test_and_clear_bit(ID_B, &motg->inputs) |
983 test_and_clear_bit(ID_C, &motg->inputs);
984 if (ret) {
985 dev_dbg(otg->dev, "ID A/B/C is no more\n");
986 motg->chg_type = USB_INVALID_CHARGER;
987 motg->chg_state = USB_CHG_STATE_UNDEFINED;
988 }
989 }
990out:
991 return ret;
992}
993
994static void msm_chg_enable_aca_det(struct msm_otg *motg)
995{
996 struct otg_transceiver *otg = &motg->otg;
997
998 switch (motg->pdata->phy_type) {
999 case SNPS_28NM_INTEGRATED_PHY:
1000 /* ACA ID pin resistance detection enable */
1001 ulpi_write(otg, 0x20, 0x85);
1002 break;
1003 default:
1004 break;
1005 }
1006}
1007
1008static void msm_chg_enable_aca_intr(struct msm_otg *motg)
1009{
1010 struct otg_transceiver *otg = &motg->otg;
1011
1012 switch (motg->pdata->phy_type) {
1013 case SNPS_28NM_INTEGRATED_PHY:
1014 /* Enables ACA Detection interrupt (on any RID change) */
1015 ulpi_write(otg, 0x20, 0x94);
1016 break;
1017 default:
1018 break;
1019 }
1020}
1021
1022static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1023{
1024 struct otg_transceiver *otg = &motg->otg;
1025 bool ret = false;
1026
1027 switch (motg->pdata->phy_type) {
1028 case SNPS_28NM_INTEGRATED_PHY:
1029 if (ulpi_read(otg, 0x91) & 1) {
1030 dev_dbg(otg->dev, "RID change\n");
1031 ulpi_write(otg, 0x01, 0x92);
1032 ret = msm_chg_aca_detect(motg);
1033 }
1034 default:
1035 break;
1036 }
1037 return ret;
1038}
1039#endif
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301040static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1041{
1042 struct otg_transceiver *otg = &motg->otg;
1043 u32 chg_det;
1044 bool ret = false;
1045
1046 switch (motg->pdata->phy_type) {
1047 case CI_45NM_INTEGRATED_PHY:
1048 chg_det = ulpi_read(otg, 0x34);
1049 ret = chg_det & (1 << 4);
1050 break;
1051 case SNPS_28NM_INTEGRATED_PHY:
1052 chg_det = ulpi_read(otg, 0x87);
1053 ret = chg_det & 1;
1054 break;
1055 default:
1056 break;
1057 }
1058 return ret;
1059}
1060
1061static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1062{
1063 struct otg_transceiver *otg = &motg->otg;
1064 u32 chg_det;
1065
1066 switch (motg->pdata->phy_type) {
1067 case CI_45NM_INTEGRATED_PHY:
1068 chg_det = ulpi_read(otg, 0x34);
1069 /* Turn off charger block */
1070 chg_det |= ~(1 << 1);
1071 ulpi_write(otg, chg_det, 0x34);
1072 udelay(20);
1073 /* control chg block via ULPI */
1074 chg_det &= ~(1 << 3);
1075 ulpi_write(otg, chg_det, 0x34);
1076 /* put it in host mode for enabling D- source */
1077 chg_det &= ~(1 << 2);
1078 ulpi_write(otg, chg_det, 0x34);
1079 /* Turn on chg detect block */
1080 chg_det &= ~(1 << 1);
1081 ulpi_write(otg, chg_det, 0x34);
1082 udelay(20);
1083 /* enable chg detection */
1084 chg_det &= ~(1 << 0);
1085 ulpi_write(otg, chg_det, 0x34);
1086 break;
1087 case SNPS_28NM_INTEGRATED_PHY:
1088 /*
1089 * Configure DM as current source, DP as current sink
1090 * and enable battery charging comparators.
1091 */
1092 ulpi_write(otg, 0x8, 0x85);
1093 ulpi_write(otg, 0x2, 0x85);
1094 ulpi_write(otg, 0x1, 0x85);
1095 break;
1096 default:
1097 break;
1098 }
1099}
1100
1101static bool msm_chg_check_primary_det(struct msm_otg *motg)
1102{
1103 struct otg_transceiver *otg = &motg->otg;
1104 u32 chg_det;
1105 bool ret = false;
1106
1107 switch (motg->pdata->phy_type) {
1108 case CI_45NM_INTEGRATED_PHY:
1109 chg_det = ulpi_read(otg, 0x34);
1110 ret = chg_det & (1 << 4);
1111 break;
1112 case SNPS_28NM_INTEGRATED_PHY:
1113 chg_det = ulpi_read(otg, 0x87);
1114 ret = chg_det & 1;
1115 break;
1116 default:
1117 break;
1118 }
1119 return ret;
1120}
1121
1122static void msm_chg_enable_primary_det(struct msm_otg *motg)
1123{
1124 struct otg_transceiver *otg = &motg->otg;
1125 u32 chg_det;
1126
1127 switch (motg->pdata->phy_type) {
1128 case CI_45NM_INTEGRATED_PHY:
1129 chg_det = ulpi_read(otg, 0x34);
1130 /* enable chg detection */
1131 chg_det &= ~(1 << 0);
1132 ulpi_write(otg, chg_det, 0x34);
1133 break;
1134 case SNPS_28NM_INTEGRATED_PHY:
1135 /*
1136 * Configure DP as current source, DM as current sink
1137 * and enable battery charging comparators.
1138 */
1139 ulpi_write(otg, 0x2, 0x85);
1140 ulpi_write(otg, 0x1, 0x85);
1141 break;
1142 default:
1143 break;
1144 }
1145}
1146
1147static bool msm_chg_check_dcd(struct msm_otg *motg)
1148{
1149 struct otg_transceiver *otg = &motg->otg;
1150 u32 line_state;
1151 bool ret = false;
1152
1153 switch (motg->pdata->phy_type) {
1154 case CI_45NM_INTEGRATED_PHY:
1155 line_state = ulpi_read(otg, 0x15);
1156 ret = !(line_state & 1);
1157 break;
1158 case SNPS_28NM_INTEGRATED_PHY:
1159 line_state = ulpi_read(otg, 0x87);
1160 ret = line_state & 2;
1161 break;
1162 default:
1163 break;
1164 }
1165 return ret;
1166}
1167
1168static void msm_chg_disable_dcd(struct msm_otg *motg)
1169{
1170 struct otg_transceiver *otg = &motg->otg;
1171 u32 chg_det;
1172
1173 switch (motg->pdata->phy_type) {
1174 case CI_45NM_INTEGRATED_PHY:
1175 chg_det = ulpi_read(otg, 0x34);
1176 chg_det &= ~(1 << 5);
1177 ulpi_write(otg, chg_det, 0x34);
1178 break;
1179 case SNPS_28NM_INTEGRATED_PHY:
1180 ulpi_write(otg, 0x10, 0x86);
1181 break;
1182 default:
1183 break;
1184 }
1185}
1186
1187static void msm_chg_enable_dcd(struct msm_otg *motg)
1188{
1189 struct otg_transceiver *otg = &motg->otg;
1190 u32 chg_det;
1191
1192 switch (motg->pdata->phy_type) {
1193 case CI_45NM_INTEGRATED_PHY:
1194 chg_det = ulpi_read(otg, 0x34);
1195 /* Turn on D+ current source */
1196 chg_det |= (1 << 5);
1197 ulpi_write(otg, chg_det, 0x34);
1198 break;
1199 case SNPS_28NM_INTEGRATED_PHY:
1200 /* Data contact detection enable */
1201 ulpi_write(otg, 0x10, 0x85);
1202 break;
1203 default:
1204 break;
1205 }
1206}
1207
1208static void msm_chg_block_on(struct msm_otg *motg)
1209{
1210 struct otg_transceiver *otg = &motg->otg;
1211 u32 func_ctrl, chg_det;
1212
1213 /* put the controller in non-driving mode */
1214 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1215 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1216 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1217 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1218
1219 switch (motg->pdata->phy_type) {
1220 case CI_45NM_INTEGRATED_PHY:
1221 chg_det = ulpi_read(otg, 0x34);
1222 /* control chg block via ULPI */
1223 chg_det &= ~(1 << 3);
1224 ulpi_write(otg, chg_det, 0x34);
1225 /* Turn on chg detect block */
1226 chg_det &= ~(1 << 1);
1227 ulpi_write(otg, chg_det, 0x34);
1228 udelay(20);
1229 break;
1230 case SNPS_28NM_INTEGRATED_PHY:
1231 /* Clear charger detecting control bits */
1232 ulpi_write(otg, 0x3F, 0x86);
1233 /* Clear alt interrupt latch and enable bits */
1234 ulpi_write(otg, 0x1F, 0x92);
1235 ulpi_write(otg, 0x1F, 0x95);
1236 udelay(100);
1237 break;
1238 default:
1239 break;
1240 }
1241}
1242
1243static void msm_chg_block_off(struct msm_otg *motg)
1244{
1245 struct otg_transceiver *otg = &motg->otg;
1246 u32 func_ctrl, chg_det;
1247
1248 switch (motg->pdata->phy_type) {
1249 case CI_45NM_INTEGRATED_PHY:
1250 chg_det = ulpi_read(otg, 0x34);
1251 /* Turn off charger block */
1252 chg_det |= ~(1 << 1);
1253 ulpi_write(otg, chg_det, 0x34);
1254 break;
1255 case SNPS_28NM_INTEGRATED_PHY:
1256 /* Clear charger detecting control bits */
1257 ulpi_write(otg, 0x3F, 0x86);
1258 /* Clear alt interrupt latch and enable bits */
1259 ulpi_write(otg, 0x1F, 0x92);
1260 ulpi_write(otg, 0x1F, 0x95);
1261 break;
1262 default:
1263 break;
1264 }
1265
1266 /* put the controller in normal mode */
1267 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1268 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1269 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1270 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1271}
1272
Anji jonnalad270e2d2011-08-09 11:28:32 +05301273static const char *chg_to_string(enum usb_chg_type chg_type)
1274{
1275 switch (chg_type) {
1276 case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
1277 case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
1278 case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
1279 case USB_ACA_A_CHARGER: return "USB_ACA_A_CHARGER";
1280 case USB_ACA_B_CHARGER: return "USB_ACA_B_CHARGER";
1281 case USB_ACA_C_CHARGER: return "USB_ACA_C_CHARGER";
1282 case USB_ACA_DOCK_CHARGER: return "USB_ACA_DOCK_CHARGER";
1283 default: return "INVALID_CHARGER";
1284 }
1285}
1286
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301287#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1288#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
1289#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
1290#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
1291static void msm_chg_detect_work(struct work_struct *w)
1292{
1293 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1294 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001295 bool is_dcd, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301296 unsigned long delay;
1297
1298 dev_dbg(otg->dev, "chg detection work\n");
1299 switch (motg->chg_state) {
1300 case USB_CHG_STATE_UNDEFINED:
1301 pm_runtime_get_sync(otg->dev);
1302 msm_chg_block_on(motg);
1303 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001304 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301305 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1306 motg->dcd_retries = 0;
1307 delay = MSM_CHG_DCD_POLL_TIME;
1308 break;
1309 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001310 is_aca = msm_chg_aca_detect(motg);
1311 if (is_aca) {
1312 /*
1313 * ID_A can be ACA dock too. continue
1314 * primary detection after DCD.
1315 */
1316 if (test_bit(ID_A, &motg->inputs)) {
1317 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1318 } else {
1319 delay = 0;
1320 break;
1321 }
1322 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301323 is_dcd = msm_chg_check_dcd(motg);
1324 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1325 if (is_dcd || tmout) {
1326 msm_chg_disable_dcd(motg);
1327 msm_chg_enable_primary_det(motg);
1328 delay = MSM_CHG_PRIMARY_DET_TIME;
1329 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1330 } else {
1331 delay = MSM_CHG_DCD_POLL_TIME;
1332 }
1333 break;
1334 case USB_CHG_STATE_DCD_DONE:
1335 vout = msm_chg_check_primary_det(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001336 is_aca = msm_chg_aca_detect(motg);
1337 if (is_aca) {
1338 if (vout && test_bit(ID_A, &motg->inputs))
1339 motg->chg_type = USB_ACA_DOCK_CHARGER;
1340 delay = 0;
1341 break;
1342 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301343 if (vout) {
1344 msm_chg_enable_secondary_det(motg);
1345 delay = MSM_CHG_SECONDARY_DET_TIME;
1346 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1347 } else {
1348 motg->chg_type = USB_SDP_CHARGER;
1349 motg->chg_state = USB_CHG_STATE_DETECTED;
1350 delay = 0;
1351 }
1352 break;
1353 case USB_CHG_STATE_PRIMARY_DONE:
1354 vout = msm_chg_check_secondary_det(motg);
1355 if (vout)
1356 motg->chg_type = USB_DCP_CHARGER;
1357 else
1358 motg->chg_type = USB_CDP_CHARGER;
1359 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1360 /* fall through */
1361 case USB_CHG_STATE_SECONDARY_DONE:
1362 motg->chg_state = USB_CHG_STATE_DETECTED;
1363 case USB_CHG_STATE_DETECTED:
1364 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001365 msm_chg_enable_aca_det(motg);
1366 msm_chg_enable_aca_intr(motg);
Anji jonnalad270e2d2011-08-09 11:28:32 +05301367 dev_dbg(otg->dev, "chg_type = %s\n",
1368 chg_to_string(motg->chg_type));
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301369 schedule_work(&motg->sm_work);
1370 return;
1371 default:
1372 return;
1373 }
1374
1375 schedule_delayed_work(&motg->chg_work, delay);
1376}
1377
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301378/*
1379 * We support OTG, Peripheral only and Host only configurations. In case
1380 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1381 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1382 * enabled when switch is controlled by user and default mode is supplied
1383 * by board file, which can be changed by userspace later.
1384 */
1385static void msm_otg_init_sm(struct msm_otg *motg)
1386{
1387 struct msm_otg_platform_data *pdata = motg->pdata;
1388 u32 otgsc = readl(USB_OTGSC);
1389
1390 switch (pdata->mode) {
1391 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001392 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301393 if (pdata->default_mode == USB_HOST) {
1394 clear_bit(ID, &motg->inputs);
1395 } else if (pdata->default_mode == USB_PERIPHERAL) {
1396 set_bit(ID, &motg->inputs);
1397 set_bit(B_SESS_VLD, &motg->inputs);
1398 } else {
1399 set_bit(ID, &motg->inputs);
1400 clear_bit(B_SESS_VLD, &motg->inputs);
1401 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001402 } else {
1403 if (otgsc & OTGSC_ID)
1404 set_bit(ID, &motg->inputs);
1405 else
1406 clear_bit(ID, &motg->inputs);
1407
1408 if (otgsc & OTGSC_BSV)
1409 set_bit(B_SESS_VLD, &motg->inputs);
1410 else
1411 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301412 }
1413 break;
1414 case USB_HOST:
1415 clear_bit(ID, &motg->inputs);
1416 break;
1417 case USB_PERIPHERAL:
1418 set_bit(ID, &motg->inputs);
1419 if (otgsc & OTGSC_BSV)
1420 set_bit(B_SESS_VLD, &motg->inputs);
1421 else
1422 clear_bit(B_SESS_VLD, &motg->inputs);
1423 break;
1424 default:
1425 break;
1426 }
1427}
1428
1429static void msm_otg_sm_work(struct work_struct *w)
1430{
1431 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
1432 struct otg_transceiver *otg = &motg->otg;
1433
1434 switch (otg->state) {
1435 case OTG_STATE_UNDEFINED:
1436 dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
1437 msm_otg_reset(otg);
1438 msm_otg_init_sm(motg);
1439 otg->state = OTG_STATE_B_IDLE;
1440 /* FALL THROUGH */
1441 case OTG_STATE_B_IDLE:
1442 dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001443 if ((!test_bit(ID, &motg->inputs) ||
1444 test_bit(ID_A, &motg->inputs)) && otg->host) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301445 /* disable BSV bit */
1446 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001447 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
1448 msm_otg_notify_charger(motg,
1449 IDEV_CHG_MAX);
1450 else if (!test_bit(ID_A, &motg->inputs) &&
1451 motg->pdata->vbus_power)
1452 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301453 msm_otg_start_host(otg, 1);
1454 otg->state = OTG_STATE_A_HOST;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301455 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1456 switch (motg->chg_state) {
1457 case USB_CHG_STATE_UNDEFINED:
1458 msm_chg_detect_work(&motg->chg_work.work);
1459 break;
1460 case USB_CHG_STATE_DETECTED:
1461 switch (motg->chg_type) {
1462 case USB_DCP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001463 case USB_ACA_B_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301464 msm_otg_notify_charger(motg,
1465 IDEV_CHG_MAX);
1466 break;
1467 case USB_CDP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001468 case USB_ACA_C_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301469 msm_otg_notify_charger(motg,
1470 IDEV_CHG_MAX);
1471 msm_otg_start_peripheral(otg, 1);
1472 otg->state = OTG_STATE_B_PERIPHERAL;
1473 break;
1474 case USB_SDP_CHARGER:
1475 msm_otg_notify_charger(motg, IUNIT);
1476 msm_otg_start_peripheral(otg, 1);
1477 otg->state = OTG_STATE_B_PERIPHERAL;
1478 break;
1479 default:
1480 break;
1481 }
1482 break;
1483 default:
1484 break;
1485 }
1486 } else {
1487 /*
1488 * If charger detection work is pending, decrement
1489 * the pm usage counter to balance with the one that
1490 * is incremented in charger detection work.
1491 */
1492 if (cancel_delayed_work_sync(&motg->chg_work)) {
1493 pm_runtime_put_sync(otg->dev);
1494 msm_otg_reset(otg);
1495 }
1496 msm_otg_notify_charger(motg, 0);
1497 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1498 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301499 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301500 pm_runtime_put_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301501 break;
1502 case OTG_STATE_B_PERIPHERAL:
1503 dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
1504 if (!test_bit(B_SESS_VLD, &motg->inputs) ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001505 !test_bit(ID, &motg->inputs) ||
1506 !test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301507 msm_otg_notify_charger(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301508 msm_otg_start_peripheral(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001509 if (!test_bit(ID_B, &motg->inputs) &&
1510 !test_bit(ID_A, &motg->inputs)) {
1511 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1512 motg->chg_type = USB_INVALID_CHARGER;
1513 }
1514 otg->state = OTG_STATE_B_IDLE;
1515 msm_otg_reset(otg);
1516 schedule_work(w);
1517 } else if (test_bit(ID_C, &motg->inputs)) {
1518 msm_otg_notify_charger(motg, IDEV_CHG_MAX);
1519 pm_runtime_put_sync(otg->dev);
1520 }
1521 break;
1522 case OTG_STATE_A_HOST:
1523 dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
1524 if (test_bit(ID, &motg->inputs) &&
1525 !test_bit(ID_A, &motg->inputs)) {
1526 msm_otg_start_host(otg, 0);
1527 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1528 if (motg->pdata->vbus_power)
1529 motg->pdata->vbus_power(0);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301530 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1531 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301532 otg->state = OTG_STATE_B_IDLE;
1533 msm_otg_reset(otg);
1534 schedule_work(w);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001535 } else if (test_bit(ID_A, &motg->inputs)) {
1536 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1537 if (motg->pdata->vbus_power)
1538 motg->pdata->vbus_power(0);
1539 msm_otg_notify_charger(motg,
1540 IDEV_CHG_MIN - motg->mA_port);
1541 pm_runtime_put_sync(otg->dev);
1542 } else if (!test_bit(ID, &motg->inputs)) {
1543 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1544 motg->chg_type = USB_INVALID_CHARGER;
1545 msm_otg_notify_charger(motg, 0);
1546 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1547 if (motg->pdata->vbus_power)
1548 motg->pdata->vbus_power(1);
1549 pm_runtime_put_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301550 }
1551 break;
1552 default:
1553 break;
1554 }
1555}
1556
1557static irqreturn_t msm_otg_irq(int irq, void *data)
1558{
1559 struct msm_otg *motg = data;
1560 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001561 u32 otgsc = 0, usbsts;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301562
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301563 if (atomic_read(&motg->in_lpm)) {
1564 disable_irq_nosync(irq);
1565 motg->async_int = 1;
1566 pm_runtime_get(otg->dev);
1567 return IRQ_HANDLED;
1568 }
1569
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001570 usbsts = readl(USB_USBSTS);
1571 if ((usbsts & PHY_ALT_INT)) {
1572 writel(PHY_ALT_INT, USB_USBSTS);
1573 if (msm_chg_check_aca_intr(motg)) {
1574 pm_runtime_get_noresume(otg->dev);
1575 schedule_work(&motg->sm_work);
1576 }
1577 return IRQ_HANDLED;
1578 }
1579
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301580 otgsc = readl(USB_OTGSC);
1581 if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1582 return IRQ_NONE;
1583
1584 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
1585 if (otgsc & OTGSC_ID)
1586 set_bit(ID, &motg->inputs);
1587 else
1588 clear_bit(ID, &motg->inputs);
1589 dev_dbg(otg->dev, "ID set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001590 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301591 pm_runtime_get_noresume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301592 } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
1593 if (otgsc & OTGSC_BSV)
1594 set_bit(B_SESS_VLD, &motg->inputs);
1595 else
1596 clear_bit(B_SESS_VLD, &motg->inputs);
1597 dev_dbg(otg->dev, "BSV set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001598 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301599 pm_runtime_get_noresume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301600 }
1601
1602 writel(otgsc, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001603 return IRQ_HANDLED;
1604}
1605
1606static void msm_otg_set_vbus_state(int online)
1607{
1608 struct msm_otg *motg = the_msm_otg;
1609
1610 /* We depend on PMIC for only VBUS ON interrupt */
1611 if (!atomic_read(&motg->in_lpm) || !online)
1612 return;
1613
1614 /*
1615 * Let interrupt handler take care of resuming
1616 * the hardware.
1617 */
1618 msm_otg_irq(motg->irq, (void *) motg);
1619}
1620
1621static irqreturn_t msm_pmic_id_irq(int irq, void *data)
1622{
1623 struct msm_otg *motg = data;
1624
1625 if (atomic_read(&motg->in_lpm) && !motg->async_int)
1626 msm_otg_irq(motg->irq, motg);
1627
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301628 return IRQ_HANDLED;
1629}
1630
1631static int msm_otg_mode_show(struct seq_file *s, void *unused)
1632{
1633 struct msm_otg *motg = s->private;
1634 struct otg_transceiver *otg = &motg->otg;
1635
1636 switch (otg->state) {
1637 case OTG_STATE_A_HOST:
1638 seq_printf(s, "host\n");
1639 break;
1640 case OTG_STATE_B_PERIPHERAL:
1641 seq_printf(s, "peripheral\n");
1642 break;
1643 default:
1644 seq_printf(s, "none\n");
1645 break;
1646 }
1647
1648 return 0;
1649}
1650
1651static int msm_otg_mode_open(struct inode *inode, struct file *file)
1652{
1653 return single_open(file, msm_otg_mode_show, inode->i_private);
1654}
1655
1656static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1657 size_t count, loff_t *ppos)
1658{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05301659 struct seq_file *s = file->private_data;
1660 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301661 char buf[16];
1662 struct otg_transceiver *otg = &motg->otg;
1663 int status = count;
1664 enum usb_mode_type req_mode;
1665
1666 memset(buf, 0x00, sizeof(buf));
1667
1668 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1669 status = -EFAULT;
1670 goto out;
1671 }
1672
1673 if (!strncmp(buf, "host", 4)) {
1674 req_mode = USB_HOST;
1675 } else if (!strncmp(buf, "peripheral", 10)) {
1676 req_mode = USB_PERIPHERAL;
1677 } else if (!strncmp(buf, "none", 4)) {
1678 req_mode = USB_NONE;
1679 } else {
1680 status = -EINVAL;
1681 goto out;
1682 }
1683
1684 switch (req_mode) {
1685 case USB_NONE:
1686 switch (otg->state) {
1687 case OTG_STATE_A_HOST:
1688 case OTG_STATE_B_PERIPHERAL:
1689 set_bit(ID, &motg->inputs);
1690 clear_bit(B_SESS_VLD, &motg->inputs);
1691 break;
1692 default:
1693 goto out;
1694 }
1695 break;
1696 case USB_PERIPHERAL:
1697 switch (otg->state) {
1698 case OTG_STATE_B_IDLE:
1699 case OTG_STATE_A_HOST:
1700 set_bit(ID, &motg->inputs);
1701 set_bit(B_SESS_VLD, &motg->inputs);
1702 break;
1703 default:
1704 goto out;
1705 }
1706 break;
1707 case USB_HOST:
1708 switch (otg->state) {
1709 case OTG_STATE_B_IDLE:
1710 case OTG_STATE_B_PERIPHERAL:
1711 clear_bit(ID, &motg->inputs);
1712 break;
1713 default:
1714 goto out;
1715 }
1716 break;
1717 default:
1718 goto out;
1719 }
1720
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301721 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301722 schedule_work(&motg->sm_work);
1723out:
1724 return status;
1725}
1726
1727const struct file_operations msm_otg_mode_fops = {
1728 .open = msm_otg_mode_open,
1729 .read = seq_read,
1730 .write = msm_otg_mode_write,
1731 .llseek = seq_lseek,
1732 .release = single_release,
1733};
1734
Anji jonnalad270e2d2011-08-09 11:28:32 +05301735static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
1736{
1737 struct msm_otg *motg = s->private;
1738
1739 seq_printf(s, chg_to_string(motg->chg_type));
1740 return 0;
1741}
1742
1743static int msm_otg_chg_open(struct inode *inode, struct file *file)
1744{
1745 return single_open(file, msm_otg_show_chg_type, inode->i_private);
1746}
1747
1748const struct file_operations msm_otg_chg_fops = {
1749 .open = msm_otg_chg_open,
1750 .read = seq_read,
1751 .llseek = seq_lseek,
1752 .release = single_release,
1753};
1754
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301755static struct dentry *msm_otg_dbg_root;
1756static struct dentry *msm_otg_dbg_mode;
Anji jonnalad270e2d2011-08-09 11:28:32 +05301757static struct dentry *msm_otg_chg_type;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301758
1759static int msm_otg_debugfs_init(struct msm_otg *motg)
1760{
Anji jonnalad270e2d2011-08-09 11:28:32 +05301761
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301762 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
1763
1764 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
1765 return -ENODEV;
1766
Anji jonnalad270e2d2011-08-09 11:28:32 +05301767 if (motg->pdata->mode == USB_OTG &&
1768 motg->pdata->otg_control == OTG_USER_CONTROL) {
1769
1770 msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
1771 S_IWUSR, msm_otg_dbg_root, motg,
1772 &msm_otg_mode_fops);
1773
1774 if (!msm_otg_dbg_mode) {
1775 debugfs_remove(msm_otg_dbg_root);
1776 msm_otg_dbg_root = NULL;
1777 return -ENODEV;
1778 }
1779 }
1780
1781 msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
1782 msm_otg_dbg_root, motg,
1783 &msm_otg_chg_fops);
1784
1785 if (!msm_otg_chg_type) {
1786 debugfs_remove(msm_otg_dbg_mode);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301787 debugfs_remove(msm_otg_dbg_root);
1788 msm_otg_dbg_root = NULL;
Anji jonnalad270e2d2011-08-09 11:28:32 +05301789 msm_otg_dbg_mode = NULL;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301790 return -ENODEV;
1791 }
1792
1793 return 0;
1794}
1795
1796static void msm_otg_debugfs_cleanup(void)
1797{
Anji jonnalad270e2d2011-08-09 11:28:32 +05301798 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301799}
1800
1801static int __init msm_otg_probe(struct platform_device *pdev)
1802{
1803 int ret = 0;
1804 struct resource *res;
1805 struct msm_otg *motg;
1806 struct otg_transceiver *otg;
1807
1808 dev_info(&pdev->dev, "msm_otg probe\n");
1809 if (!pdev->dev.platform_data) {
1810 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
1811 return -ENODEV;
1812 }
1813
1814 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
1815 if (!motg) {
1816 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
1817 return -ENOMEM;
1818 }
1819
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001820 the_msm_otg = motg;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301821 motg->pdata = pdev->dev.platform_data;
1822 otg = &motg->otg;
1823 otg->dev = &pdev->dev;
1824
Amit Blay02eff132011-09-21 16:46:24 +03001825 /* Some targets don't support PHY clock. */
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301826 motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
Amit Blay02eff132011-09-21 16:46:24 +03001827 if (IS_ERR(motg->phy_reset_clk))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301828 dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301829
1830 motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
1831 if (IS_ERR(motg->clk)) {
1832 dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
1833 ret = PTR_ERR(motg->clk);
1834 goto put_phy_reset_clk;
1835 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05301836 clk_set_rate(motg->clk, 60000000);
1837
1838 /*
1839 * If USB Core is running its protocol engine based on CORE CLK,
1840 * CORE CLK must be running at >55Mhz for correct HSUSB
1841 * operation and USB core cannot tolerate frequency changes on
1842 * CORE CLK. For such USB cores, vote for maximum clk frequency
1843 * on pclk source
1844 */
1845 if (motg->pdata->pclk_src_name) {
1846 motg->pclk_src = clk_get(&pdev->dev,
1847 motg->pdata->pclk_src_name);
1848 if (IS_ERR(motg->pclk_src))
1849 goto put_clk;
1850 clk_set_rate(motg->pclk_src, INT_MAX);
1851 clk_enable(motg->pclk_src);
1852 } else
1853 motg->pclk_src = ERR_PTR(-ENOENT);
1854
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301855 motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
1856 if (IS_ERR(motg->pclk)) {
1857 dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
1858 ret = PTR_ERR(motg->pclk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05301859 goto put_pclk_src;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301860 }
1861
Amit Blay02eff132011-09-21 16:46:24 +03001862 motg->system_clk = clk_get(&pdev->dev, "usb_hs_system_clk");
1863 if (!IS_ERR(motg->system_clk))
1864 clk_enable(motg->system_clk);
1865
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301866 /*
1867 * USB core clock is not present on all MSM chips. This
1868 * clock is introduced to remove the dependency on AXI
1869 * bus frequency.
1870 */
1871 motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
1872 if (IS_ERR(motg->core_clk))
1873 motg->core_clk = NULL;
1874
1875 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1876 if (!res) {
1877 dev_err(&pdev->dev, "failed to get platform resource mem\n");
1878 ret = -ENODEV;
1879 goto put_core_clk;
1880 }
1881
1882 motg->regs = ioremap(res->start, resource_size(res));
1883 if (!motg->regs) {
1884 dev_err(&pdev->dev, "ioremap failed\n");
1885 ret = -ENOMEM;
1886 goto put_core_clk;
1887 }
1888 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
1889
1890 motg->irq = platform_get_irq(pdev, 0);
1891 if (!motg->irq) {
1892 dev_err(&pdev->dev, "platform_get_irq failed\n");
1893 ret = -ENODEV;
1894 goto free_regs;
1895 }
1896
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301897 clk_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301898
1899 ret = msm_hsusb_init_vddcx(motg, 1);
1900 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001901 dev_err(&pdev->dev, "hsusb vddcx init failed\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +05301902 goto free_regs;
1903 }
1904
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001905 ret = msm_hsusb_config_vddcx(1);
1906 if (ret) {
1907 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
1908 goto free_init_vddcx;
1909 }
1910
Anji jonnala11aa5c42011-05-04 10:19:48 +05301911 ret = msm_hsusb_ldo_init(motg, 1);
1912 if (ret) {
1913 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001914 goto free_init_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301915 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001916
1917 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301918 if (ret) {
1919 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001920 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301921 }
1922
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301923 if (motg->core_clk)
1924 clk_enable(motg->core_clk);
1925
1926 writel(0, USB_USBINTR);
1927 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001928 /* Ensure that above STOREs are completed before enabling interrupts */
1929 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301930
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001931 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301932 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301933 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301934 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
1935 "msm_otg", motg);
1936 if (ret) {
1937 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001938 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301939 }
1940
1941 otg->init = msm_otg_reset;
1942 otg->set_host = msm_otg_set_host;
1943 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301944 otg->set_power = msm_otg_set_power;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301945
1946 otg->io_ops = &msm_otg_io_ops;
1947
1948 ret = otg_set_transceiver(&motg->otg);
1949 if (ret) {
1950 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
1951 goto free_irq;
1952 }
1953
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001954 if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
1955 if (motg->pdata->pmic_id_irq) {
1956 ret = request_irq(motg->pdata->pmic_id_irq,
1957 msm_pmic_id_irq,
1958 IRQF_TRIGGER_RISING |
1959 IRQF_TRIGGER_FALLING,
1960 "msm_otg", motg);
1961 if (ret) {
1962 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
1963 goto remove_otg;
1964 }
1965 } else {
1966 ret = -ENODEV;
1967 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
1968 goto remove_otg;
1969 }
1970 }
1971
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301972 platform_set_drvdata(pdev, motg);
1973 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001974 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301975
Anji jonnalad270e2d2011-08-09 11:28:32 +05301976 ret = msm_otg_debugfs_init(motg);
1977 if (ret)
1978 dev_dbg(&pdev->dev, "mode debugfs file is"
1979 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301980
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001981 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
1982 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
1983
1984 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
1985 motg->pdata->otg_control == OTG_PMIC_CONTROL &&
1986 motg->pdata->pmic_id_irq)
1987 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
1988 ALLOW_PHY_RETENTION |
1989 ALLOW_PHY_COMP_DISABLE;
1990
1991 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301992 pm_runtime_set_active(&pdev->dev);
1993 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301994
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301995 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001996
1997remove_otg:
1998 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301999free_irq:
2000 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002001destroy_wlock:
2002 wake_lock_destroy(&motg->wlock);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302003 clk_disable(motg->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002004 msm_hsusb_ldo_enable(motg, 0);
2005free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302006 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002007free_init_vddcx:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302008 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302009free_regs:
2010 iounmap(motg->regs);
2011put_core_clk:
2012 if (motg->core_clk)
2013 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002014
2015 if (!IS_ERR(motg->system_clk)) {
2016 clk_disable(motg->system_clk);
2017 clk_put(motg->system_clk);
2018 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302019put_pclk_src:
2020 if (!IS_ERR(motg->pclk_src)) {
2021 clk_disable(motg->pclk_src);
2022 clk_put(motg->pclk_src);
2023 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302024put_clk:
2025 clk_put(motg->clk);
2026put_phy_reset_clk:
Amit Blay02eff132011-09-21 16:46:24 +03002027 if (!IS_ERR(motg->phy_reset_clk))
2028 clk_put(motg->phy_reset_clk);
2029
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302030 kfree(motg);
2031 return ret;
2032}
2033
2034static int __devexit msm_otg_remove(struct platform_device *pdev)
2035{
2036 struct msm_otg *motg = platform_get_drvdata(pdev);
2037 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302038 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302039
2040 if (otg->host || otg->gadget)
2041 return -EBUSY;
2042
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002043 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2044 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302045 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302046 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302047 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302048
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302049 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302050
2051 device_init_wakeup(&pdev->dev, 0);
2052 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002053 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302054
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002055 if (motg->pdata->pmic_id_irq)
2056 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302057 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302058 free_irq(motg->irq, motg);
2059
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302060 /*
2061 * Put PHY in low power mode.
2062 */
2063 ulpi_read(otg, 0x14);
2064 ulpi_write(otg, 0x08, 0x09);
2065
2066 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
2067 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
2068 if (readl(USB_PORTSC) & PORTSC_PHCD)
2069 break;
2070 udelay(1);
2071 cnt++;
2072 }
2073 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
2074 dev_err(otg->dev, "Unable to suspend PHY\n");
2075
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302076 clk_disable(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302077 if (motg->core_clk)
2078 clk_disable(motg->core_clk);
Amit Blay137575f2011-11-06 15:20:54 +02002079 if (!IS_ERR(motg->system_clk))
2080 clk_disable(motg->system_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302081 if (!IS_ERR(motg->pclk_src)) {
2082 clk_disable(motg->pclk_src);
2083 clk_put(motg->pclk_src);
2084 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002085 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302086 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002087 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302088
2089 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302090 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302091
Amit Blay02eff132011-09-21 16:46:24 +03002092 if (!IS_ERR(motg->phy_reset_clk))
2093 clk_put(motg->phy_reset_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302094 clk_put(motg->pclk);
2095 clk_put(motg->clk);
2096 if (motg->core_clk)
2097 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002098 if (!IS_ERR(motg->system_clk))
2099 clk_put(motg->system_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302100
2101 kfree(motg);
2102
2103 return 0;
2104}
2105
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302106#ifdef CONFIG_PM_RUNTIME
2107static int msm_otg_runtime_idle(struct device *dev)
2108{
2109 struct msm_otg *motg = dev_get_drvdata(dev);
2110 struct otg_transceiver *otg = &motg->otg;
2111
2112 dev_dbg(dev, "OTG runtime idle\n");
2113
2114 /*
2115 * It is observed some times that a spurious interrupt
2116 * comes when PHY is put into LPM immediately after PHY reset.
2117 * This 1 sec delay also prevents entering into LPM immediately
2118 * after asynchronous interrupt.
2119 */
2120 if (otg->state != OTG_STATE_UNDEFINED)
2121 pm_schedule_suspend(dev, 1000);
2122
2123 return -EAGAIN;
2124}
2125
2126static int msm_otg_runtime_suspend(struct device *dev)
2127{
2128 struct msm_otg *motg = dev_get_drvdata(dev);
2129
2130 dev_dbg(dev, "OTG runtime suspend\n");
2131 return msm_otg_suspend(motg);
2132}
2133
2134static int msm_otg_runtime_resume(struct device *dev)
2135{
2136 struct msm_otg *motg = dev_get_drvdata(dev);
2137
2138 dev_dbg(dev, "OTG runtime resume\n");
2139 return msm_otg_resume(motg);
2140}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302141#endif
2142
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302143#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302144static int msm_otg_pm_suspend(struct device *dev)
2145{
2146 struct msm_otg *motg = dev_get_drvdata(dev);
2147
2148 dev_dbg(dev, "OTG PM suspend\n");
2149 return msm_otg_suspend(motg);
2150}
2151
2152static int msm_otg_pm_resume(struct device *dev)
2153{
2154 struct msm_otg *motg = dev_get_drvdata(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302155
2156 dev_dbg(dev, "OTG PM resume\n");
2157
Manu Gautamf284c052011-09-08 16:52:48 +05302158#ifdef CONFIG_PM_RUNTIME
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302159 /*
Manu Gautamf284c052011-09-08 16:52:48 +05302160 * Do not resume hardware as part of system resume,
2161 * rather, wait for the ASYNC INT from the h/w
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302162 */
Gregory Beanebd8ca22011-10-11 12:02:35 -07002163 return 0;
Manu Gautamf284c052011-09-08 16:52:48 +05302164#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302165
Manu Gautamf284c052011-09-08 16:52:48 +05302166 return msm_otg_resume(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302167}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302168#endif
2169
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302170#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302171static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302172 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
2173 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
2174 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302175};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302176#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302177
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302178static struct platform_driver msm_otg_driver = {
2179 .remove = __devexit_p(msm_otg_remove),
2180 .driver = {
2181 .name = DRIVER_NAME,
2182 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302183#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302184 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302185#endif
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302186 },
2187};
2188
2189static int __init msm_otg_init(void)
2190{
2191 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
2192}
2193
2194static void __exit msm_otg_exit(void)
2195{
2196 platform_driver_unregister(&msm_otg_driver);
2197}
2198
2199module_init(msm_otg_init);
2200module_exit(msm_otg_exit);
2201
2202MODULE_LICENSE("GPL v2");
2203MODULE_DESCRIPTION("MSM USB transceiver driver");