blob: c55ba6e382ae529fd5a4679f9107168c74565af1 [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 Kondetieaea7fe2011-10-27 14:46:45 +053028#include <linux/of.h>
29#include <linux/dma-mapping.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053030
31#include <linux/usb.h>
32#include <linux/usb/otg.h>
33#include <linux/usb/ulpi.h>
34#include <linux/usb/gadget.h>
35#include <linux/usb/hcd.h>
36#include <linux/usb/msm_hsusb.h>
37#include <linux/usb/msm_hsusb_hw.h>
Anji jonnala11aa5c42011-05-04 10:19:48 +053038#include <linux/regulator/consumer.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070039#include <linux/mfd/pm8xxx/pm8921-charger.h>
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +053040#include <linux/pm_qos_params.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053041
42#include <mach/clk.h>
Anji jonnala7da3f262011-12-02 17:22:14 -080043#include <mach/msm_xo.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053044
45#define MSM_USB_BASE (motg->regs)
46#define DRIVER_NAME "msm_otg"
47
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053048#define ID_TIMER_FREQ (jiffies + msecs_to_jiffies(2000))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053049#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
Anji jonnala11aa5c42011-05-04 10:19:48 +053050
51#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
52#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
53#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
54#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
55
56#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
57#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
58#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
59#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
60
Vamsi Krishna132b2762011-11-11 16:09:20 -080061#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
Anji jonnala11aa5c42011-05-04 10:19:48 +053062#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
63
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070064static struct msm_otg *the_msm_otg;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053065static bool debug_aca_enabled;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070066
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +053067/* Prevent idle power collapse(pc) while operating in peripheral mode */
68static void otg_pm_qos_update_latency(struct msm_otg *dev, int vote)
69{
70 struct msm_otg_platform_data *pdata = dev->pdata;
71 u32 swfi_latency = 0;
72
73 if (!pdata || !pdata->swfi_latency)
74 return;
75
76 swfi_latency = pdata->swfi_latency + 1;
77
78 if (vote)
79 pm_qos_update_request(&dev->pm_qos_req_dma,
80 swfi_latency);
81 else
82 pm_qos_update_request(&dev->pm_qos_req_dma,
83 PM_QOS_DEFAULT_VALUE);
84}
85
Anji jonnala11aa5c42011-05-04 10:19:48 +053086static struct regulator *hsusb_3p3;
87static struct regulator *hsusb_1p8;
88static struct regulator *hsusb_vddcx;
89
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053090static inline bool aca_enabled(void)
91{
92#ifdef CONFIG_USB_MSM_ACA
93 return true;
94#else
95 return debug_aca_enabled;
96#endif
97}
98
Anji jonnala11aa5c42011-05-04 10:19:48 +053099static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
100{
101 int ret = 0;
102
103 if (init) {
104 hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
105 if (IS_ERR(hsusb_vddcx)) {
106 dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
107 return PTR_ERR(hsusb_vddcx);
108 }
109
110 ret = regulator_set_voltage(hsusb_vddcx,
111 USB_PHY_VDD_DIG_VOL_MIN,
112 USB_PHY_VDD_DIG_VOL_MAX);
113 if (ret) {
114 dev_err(motg->otg.dev, "unable to set the voltage "
115 "for hsusb vddcx\n");
116 regulator_put(hsusb_vddcx);
117 return ret;
118 }
119
120 ret = regulator_enable(hsusb_vddcx);
121 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700122 regulator_set_voltage(hsusb_vddcx, 0,
123 USB_PHY_VDD_DIG_VOL_MIN);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530124 regulator_put(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700125 dev_err(motg->otg.dev, "unable to enable the hsusb vddcx\n");
126 return ret;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530127 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700128
Anji jonnala11aa5c42011-05-04 10:19:48 +0530129 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700130
Anji jonnala11aa5c42011-05-04 10:19:48 +0530131 ret = regulator_disable(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700132 if (ret) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530133 dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700134 return ret;
135 }
136
137 ret = regulator_set_voltage(hsusb_vddcx, 0,
138 USB_PHY_VDD_DIG_VOL_MIN);
139 if (ret) {
140 dev_err(motg->otg.dev, "unable to set the voltage"
141 "for hsusb vddcx\n");
142 return ret;
143 }
Anji jonnala11aa5c42011-05-04 10:19:48 +0530144
145 regulator_put(hsusb_vddcx);
146 }
147
148 return ret;
149}
150
151static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
152{
153 int rc = 0;
154
155 if (init) {
156 hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
157 if (IS_ERR(hsusb_3p3)) {
158 dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
159 return PTR_ERR(hsusb_3p3);
160 }
161
162 rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
163 USB_PHY_3P3_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 3p3\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530167 goto put_3p3;
168 }
169 hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
170 if (IS_ERR(hsusb_1p8)) {
171 dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
172 rc = PTR_ERR(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700173 goto put_3p3_lpm;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530174 }
175 rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
176 USB_PHY_1P8_VOL_MAX);
177 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700178 dev_err(motg->otg.dev, "unable to set voltage level for"
179 "hsusb 1p8\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530180 goto put_1p8;
181 }
182
183 return 0;
184 }
185
Anji jonnala11aa5c42011-05-04 10:19:48 +0530186put_1p8:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700187 regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530188 regulator_put(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700189put_3p3_lpm:
190 regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530191put_3p3:
192 regulator_put(hsusb_3p3);
193 return rc;
194}
195
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530196#ifdef CONFIG_PM_SLEEP
197#define USB_PHY_SUSP_DIG_VOL 500000
198static int msm_hsusb_config_vddcx(int high)
199{
200 int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
201 int min_vol;
202 int ret;
203
204 if (high)
205 min_vol = USB_PHY_VDD_DIG_VOL_MIN;
206 else
207 min_vol = USB_PHY_SUSP_DIG_VOL;
208
209 ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
210 if (ret) {
211 pr_err("%s: unable to set the voltage for regulator "
212 "HSUSB_VDDCX\n", __func__);
213 return ret;
214 }
215
216 pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
217
218 return ret;
219}
Hemant Kumar8e7bd072011-08-01 14:14:24 -0700220#else
221static int msm_hsusb_config_vddcx(int high)
222{
223 return 0;
224}
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530225#endif
226
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
Anji jonnala11aa5c42011-05-04 10:19:48 +0530228{
229 int ret = 0;
230
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530231 if (IS_ERR(hsusb_1p8)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530232 pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
233 return -ENODEV;
234 }
235
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530236 if (IS_ERR(hsusb_3p3)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530237 pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
238 return -ENODEV;
239 }
240
241 if (on) {
242 ret = regulator_set_optimum_mode(hsusb_1p8,
243 USB_PHY_1P8_HPM_LOAD);
244 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700245 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530246 "HSUSB_1p8\n", __func__);
247 return ret;
248 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700249
250 ret = regulator_enable(hsusb_1p8);
251 if (ret) {
252 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 1p8\n",
253 __func__);
254 regulator_set_optimum_mode(hsusb_1p8, 0);
255 return ret;
256 }
257
Anji jonnala11aa5c42011-05-04 10:19:48 +0530258 ret = regulator_set_optimum_mode(hsusb_3p3,
259 USB_PHY_3P3_HPM_LOAD);
260 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700261 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530262 "HSUSB_3p3\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263 regulator_set_optimum_mode(hsusb_1p8, 0);
264 regulator_disable(hsusb_1p8);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530265 return ret;
266 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700267
268 ret = regulator_enable(hsusb_3p3);
269 if (ret) {
270 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 3p3\n",
271 __func__);
272 regulator_set_optimum_mode(hsusb_3p3, 0);
273 regulator_set_optimum_mode(hsusb_1p8, 0);
274 regulator_disable(hsusb_1p8);
275 return ret;
276 }
277
Anji jonnala11aa5c42011-05-04 10:19:48 +0530278 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700279 ret = regulator_disable(hsusb_1p8);
280 if (ret) {
281 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 1p8\n",
282 __func__);
283 return ret;
284 }
285
286 ret = regulator_set_optimum_mode(hsusb_1p8, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530287 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700288 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530289 "HSUSB_1p8\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290
291 ret = regulator_disable(hsusb_3p3);
292 if (ret) {
293 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 3p3\n",
294 __func__);
295 return ret;
296 }
297 ret = regulator_set_optimum_mode(hsusb_3p3, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530298 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700299 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530300 "HSUSB_3p3\n", __func__);
301 }
302
303 pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
304 return ret < 0 ? ret : 0;
305}
306
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530307static void msm_hsusb_mhl_switch_enable(struct msm_otg *motg, bool on)
308{
309 static struct regulator *mhl_analog_switch;
310 struct msm_otg_platform_data *pdata = motg->pdata;
311
312 if (!pdata->mhl_enable)
313 return;
314
315 if (on) {
316 mhl_analog_switch = regulator_get(motg->otg.dev,
317 "mhl_ext_3p3v");
318 if (IS_ERR(mhl_analog_switch)) {
319 pr_err("Unable to get mhl_analog_switch\n");
320 return;
321 }
322
323 if (regulator_enable(mhl_analog_switch)) {
324 pr_err("unable to enable mhl_analog_switch\n");
325 goto put_analog_switch;
326 }
327 return;
328 }
329
330 regulator_disable(mhl_analog_switch);
331put_analog_switch:
332 regulator_put(mhl_analog_switch);
333}
334
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530335static int ulpi_read(struct otg_transceiver *otg, u32 reg)
336{
337 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
338 int cnt = 0;
339
340 /* initiate read operation */
341 writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
342 USB_ULPI_VIEWPORT);
343
344 /* wait for completion */
345 while (cnt < ULPI_IO_TIMEOUT_USEC) {
346 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
347 break;
348 udelay(1);
349 cnt++;
350 }
351
352 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
353 dev_err(otg->dev, "ulpi_read: timeout %08x\n",
354 readl(USB_ULPI_VIEWPORT));
355 return -ETIMEDOUT;
356 }
357 return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
358}
359
360static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
361{
362 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
363 int cnt = 0;
364
365 /* initiate write operation */
366 writel(ULPI_RUN | ULPI_WRITE |
367 ULPI_ADDR(reg) | ULPI_DATA(val),
368 USB_ULPI_VIEWPORT);
369
370 /* wait for completion */
371 while (cnt < ULPI_IO_TIMEOUT_USEC) {
372 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
373 break;
374 udelay(1);
375 cnt++;
376 }
377
378 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
379 dev_err(otg->dev, "ulpi_write: timeout\n");
380 return -ETIMEDOUT;
381 }
382 return 0;
383}
384
385static struct otg_io_access_ops msm_otg_io_ops = {
386 .read = ulpi_read,
387 .write = ulpi_write,
388};
389
390static void ulpi_init(struct msm_otg *motg)
391{
392 struct msm_otg_platform_data *pdata = motg->pdata;
393 int *seq = pdata->phy_init_seq;
394
395 if (!seq)
396 return;
397
398 while (seq[0] >= 0) {
399 dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
400 seq[0], seq[1]);
401 ulpi_write(&motg->otg, seq[0], seq[1]);
402 seq += 2;
403 }
404}
405
406static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
407{
408 int ret;
409
410 if (assert) {
411 ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
412 if (ret)
413 dev_err(motg->otg.dev, "usb hs_clk assert failed\n");
414 } else {
415 ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
416 if (ret)
417 dev_err(motg->otg.dev, "usb hs_clk deassert failed\n");
418 }
419 return ret;
420}
421
422static int msm_otg_phy_clk_reset(struct msm_otg *motg)
423{
424 int ret;
425
Amit Blay02eff132011-09-21 16:46:24 +0300426 if (IS_ERR(motg->phy_reset_clk))
427 return 0;
428
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530429 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
430 if (ret) {
431 dev_err(motg->otg.dev, "usb phy clk assert failed\n");
432 return ret;
433 }
434 usleep_range(10000, 12000);
435 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
436 if (ret)
437 dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
438 return ret;
439}
440
441static int msm_otg_phy_reset(struct msm_otg *motg)
442{
443 u32 val;
444 int ret;
445 int retries;
446
447 ret = msm_otg_link_clk_reset(motg, 1);
448 if (ret)
449 return ret;
450 ret = msm_otg_phy_clk_reset(motg);
451 if (ret)
452 return ret;
453 ret = msm_otg_link_clk_reset(motg, 0);
454 if (ret)
455 return ret;
456
457 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
458 writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
459
460 for (retries = 3; retries > 0; retries--) {
461 ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
462 ULPI_CLR(ULPI_FUNC_CTRL));
463 if (!ret)
464 break;
465 ret = msm_otg_phy_clk_reset(motg);
466 if (ret)
467 return ret;
468 }
469 if (!retries)
470 return -ETIMEDOUT;
471
472 /* This reset calibrates the phy, if the above write succeeded */
473 ret = msm_otg_phy_clk_reset(motg);
474 if (ret)
475 return ret;
476
477 for (retries = 3; retries > 0; retries--) {
478 ret = ulpi_read(&motg->otg, ULPI_DEBUG);
479 if (ret != -ETIMEDOUT)
480 break;
481 ret = msm_otg_phy_clk_reset(motg);
482 if (ret)
483 return ret;
484 }
485 if (!retries)
486 return -ETIMEDOUT;
487
488 dev_info(motg->otg.dev, "phy_reset: success\n");
489 return 0;
490}
491
492#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530493static int msm_otg_link_reset(struct msm_otg *motg)
494{
495 int cnt = 0;
496
497 writel_relaxed(USBCMD_RESET, USB_USBCMD);
498 while (cnt < LINK_RESET_TIMEOUT_USEC) {
499 if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
500 break;
501 udelay(1);
502 cnt++;
503 }
504 if (cnt >= LINK_RESET_TIMEOUT_USEC)
505 return -ETIMEDOUT;
506
507 /* select ULPI phy */
508 writel_relaxed(0x80000000, USB_PORTSC);
509 writel_relaxed(0x0, USB_AHBBURST);
510 writel_relaxed(0x00, USB_AHBMODE);
511
512 return 0;
513}
514
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530515static int msm_otg_reset(struct otg_transceiver *otg)
516{
517 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
518 struct msm_otg_platform_data *pdata = motg->pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530519 int ret;
520 u32 val = 0;
521 u32 ulpi_val = 0;
522
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523 clk_enable(motg->clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530524 ret = msm_otg_phy_reset(motg);
525 if (ret) {
526 dev_err(otg->dev, "phy_reset failed\n");
527 return ret;
528 }
529
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530530 ret = msm_otg_link_reset(motg);
531 if (ret) {
532 dev_err(otg->dev, "link reset failed\n");
533 return ret;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530534 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530535 msleep(100);
Anji jonnalaa8b8d732011-12-06 10:03:24 +0530536
537 ulpi_init(motg);
538
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700539 /* Ensure that RESET operation is completed before turning off clock */
540 mb();
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530541
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700542 clk_disable(motg->clk);
543
544 val = readl_relaxed(USB_OTGSC);
545 if (pdata->mode == USB_OTG) {
546 ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
547 val |= OTGSC_IDIE | OTGSC_BSVIE;
548 } else if (pdata->mode == USB_PERIPHERAL) {
549 ulpi_val = ULPI_INT_SESS_VALID;
550 val |= OTGSC_BSVIE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530551 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700552 writel_relaxed(val, USB_OTGSC);
553 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
554 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
555
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530556 return 0;
557}
558
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530559static int msm_otg_set_suspend(struct otg_transceiver *otg, int suspend)
560{
561 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
562
563 /*
564 * Allow bus suspend only for host mode. Device mode bus suspend
565 * is not implemented yet.
566 */
567 if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530568 /*
569 * ID_GND --> ID_A transition can not be detected in LPM.
570 * Disallow host bus suspend when ACA is enabled.
571 */
572 if (suspend && !aca_enabled())
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530573 pm_runtime_put(otg->dev);
574 else
575 pm_runtime_resume(otg->dev);
576 }
577
578 return 0;
579}
580
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530581#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530582#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
583
584#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530585static int msm_otg_suspend(struct msm_otg *motg)
586{
587 struct otg_transceiver *otg = &motg->otg;
588 struct usb_bus *bus = otg->host;
589 struct msm_otg_platform_data *pdata = motg->pdata;
590 int cnt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700591 bool session_active;
Amit Blay58b31472011-11-18 09:39:39 +0200592 u32 phy_ctrl_val = 0;
Anji jonnala7da3f262011-12-02 17:22:14 -0800593 unsigned ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530594
595 if (atomic_read(&motg->in_lpm))
596 return 0;
597
598 disable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599 session_active = (otg->host && !test_bit(ID, &motg->inputs)) ||
600 test_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530601 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530602 * Chipidea 45-nm PHY suspend sequence:
603 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530604 * Interrupt Latch Register auto-clear feature is not present
605 * in all PHY versions. Latch register is clear on read type.
606 * Clear latch register to avoid spurious wakeup from
607 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530608 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530609 * PHY comparators are disabled when PHY enters into low power
610 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
611 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
612 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530613 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530614 * PLL is not turned off when PHY enters into low power mode (LPM).
615 * Disable PLL for maximum power savings.
616 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530617
618 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
619 ulpi_read(otg, 0x14);
620 if (pdata->otg_control == OTG_PHY_CONTROL)
621 ulpi_write(otg, 0x01, 0x30);
622 ulpi_write(otg, 0x08, 0x09);
623 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530624
625 /*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700626 * Turn off the OTG comparators, if depends on PMIC for
627 * VBUS and ID notifications.
628 */
629 if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !session_active) {
630 ulpi_write(otg, OTG_COMP_DISABLE,
631 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
632 motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
633 }
634
635 /*
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530636 * PHY may take some time or even fail to enter into low power
637 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
638 * in failure case.
639 */
640 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
641 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
642 if (readl(USB_PORTSC) & PORTSC_PHCD)
643 break;
644 udelay(1);
645 cnt++;
646 }
647
648 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
649 dev_err(otg->dev, "Unable to suspend PHY\n");
650 msm_otg_reset(otg);
651 enable_irq(motg->irq);
652 return -ETIMEDOUT;
653 }
654
655 /*
656 * PHY has capability to generate interrupt asynchronously in low
657 * power mode (LPM). This interrupt is level triggered. So USB IRQ
658 * line must be disabled till async interrupt enable bit is cleared
659 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
660 * block data communication from PHY.
661 */
662 writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
663
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700664 if (motg->caps & ALLOW_PHY_RETENTION && !session_active) {
Amit Blay58b31472011-11-18 09:39:39 +0200665 phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
666 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
667 /* Enable PHY HV interrupts to wake MPM/Link */
668 phy_ctrl_val |=
669 (PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
670
671 writel_relaxed(phy_ctrl_val & ~PHY_RETEN, USB_PHY_CTRL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700672 motg->lpm_flags |= PHY_RETENTIONED;
673 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530674
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700675 /* Ensure that above operation is completed before turning off clocks */
676 mb();
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530677 clk_disable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530678 if (motg->core_clk)
679 clk_disable(motg->core_clk);
680
Amit Blay137575f2011-11-06 15:20:54 +0200681 if (!IS_ERR(motg->system_clk))
682 clk_disable(motg->system_clk);
683
Anji jonnala0f73cac2011-05-04 10:19:46 +0530684 if (!IS_ERR(motg->pclk_src))
685 clk_disable(motg->pclk_src);
686
Anji jonnala7da3f262011-12-02 17:22:14 -0800687 /* usb phy no more require TCXO clock, hence vote for TCXO disable */
688 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
689 if (ret)
690 dev_err(otg->dev, "%s failed to devote for "
691 "TCXO D0 buffer%d\n", __func__, ret);
692
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !session_active) {
694 msm_hsusb_ldo_enable(motg, 0);
695 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530696 }
697
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530698 if (motg->lpm_flags & PHY_RETENTIONED) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700699 msm_hsusb_config_vddcx(0);
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530700 msm_hsusb_mhl_switch_enable(motg, 0);
701 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700702
703 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530704 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700705 if (motg->pdata->pmic_id_irq)
706 enable_irq_wake(motg->pdata->pmic_id_irq);
707 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530708 if (bus)
709 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
710
711 atomic_set(&motg->in_lpm, 1);
712 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700713 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530714
715 dev_info(otg->dev, "USB in low power mode\n");
716
717 return 0;
718}
719
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530720static int msm_otg_resume(struct msm_otg *motg)
721{
722 struct otg_transceiver *otg = &motg->otg;
723 struct usb_bus *bus = otg->host;
724 int cnt = 0;
725 unsigned temp;
Amit Blay58b31472011-11-18 09:39:39 +0200726 u32 phy_ctrl_val = 0;
Anji jonnala7da3f262011-12-02 17:22:14 -0800727 unsigned ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530728
729 if (!atomic_read(&motg->in_lpm))
730 return 0;
731
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700732 wake_lock(&motg->wlock);
Anji jonnala7da3f262011-12-02 17:22:14 -0800733
734 /* Vote for TCXO when waking up the phy */
735 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
736 if (ret)
737 dev_err(otg->dev, "%s failed to vote for "
738 "TCXO D0 buffer%d\n", __func__, ret);
739
Anji jonnala0f73cac2011-05-04 10:19:46 +0530740 if (!IS_ERR(motg->pclk_src))
741 clk_enable(motg->pclk_src);
742
Amit Blay137575f2011-11-06 15:20:54 +0200743 if (!IS_ERR(motg->system_clk))
744 clk_enable(motg->system_clk);
745
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530746 clk_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530747 if (motg->core_clk)
748 clk_enable(motg->core_clk);
749
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700750 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
751 msm_hsusb_ldo_enable(motg, 1);
752 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
753 }
754
755 if (motg->lpm_flags & PHY_RETENTIONED) {
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530756 msm_hsusb_mhl_switch_enable(motg, 1);
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530757 msm_hsusb_config_vddcx(1);
Amit Blay58b31472011-11-18 09:39:39 +0200758 phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
759 phy_ctrl_val |= PHY_RETEN;
760 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
761 /* Disable PHY HV interrupts */
762 phy_ctrl_val &=
763 ~(PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
764 writel_relaxed(phy_ctrl_val, USB_PHY_CTRL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700765 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530766 }
767
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530768 temp = readl(USB_USBCMD);
769 temp &= ~ASYNC_INTR_CTRL;
770 temp &= ~ULPI_STP_CTRL;
771 writel(temp, USB_USBCMD);
772
773 /*
774 * PHY comes out of low power mode (LPM) in case of wakeup
775 * from asynchronous interrupt.
776 */
777 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
778 goto skip_phy_resume;
779
780 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
781 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
782 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
783 break;
784 udelay(1);
785 cnt++;
786 }
787
788 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
789 /*
790 * This is a fatal error. Reset the link and
791 * PHY. USB state can not be restored. Re-insertion
792 * of USB cable is the only way to get USB working.
793 */
794 dev_err(otg->dev, "Unable to resume USB."
795 "Re-plugin the cable\n");
796 msm_otg_reset(otg);
797 }
798
799skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800 /* Turn on the OTG comparators on resume */
801 if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
802 ulpi_write(otg, OTG_COMP_DISABLE,
803 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
804 motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
805 }
806 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530807 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808 if (motg->pdata->pmic_id_irq)
809 disable_irq_wake(motg->pdata->pmic_id_irq);
810 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530811 if (bus)
812 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
813
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530814 atomic_set(&motg->in_lpm, 0);
815
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530816 if (aca_enabled() && !irq_read_line(motg->pdata->pmic_id_irq)) {
817 clear_bit(ID, &motg->inputs);
818 schedule_work(&motg->sm_work);
819 }
820
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530821 if (motg->async_int) {
822 motg->async_int = 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530823 enable_irq(motg->irq);
824 }
825
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530826 dev_info(otg->dev, "USB exited from low power mode\n");
827
828 return 0;
829}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530830#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530831
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530832static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
833{
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530834 if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
835 motg->chg_type == USB_ACA_A_CHARGER ||
836 motg->chg_type == USB_ACA_B_CHARGER ||
837 motg->chg_type == USB_ACA_C_CHARGER) &&
838 mA > IDEV_ACA_CHG_LIMIT)
839 mA = IDEV_ACA_CHG_LIMIT;
840
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530841 if (motg->cur_power == mA)
842 return;
843
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530844 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700845 pm8921_charger_vbus_draw(mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530846 motg->cur_power = mA;
847}
848
849static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
850{
851 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
852
853 /*
854 * Gadget driver uses set_power method to notify about the
855 * available current based on suspend/configured states.
856 *
857 * IDEV_CHG can be drawn irrespective of suspend/un-configured
858 * states when CDP/ACA is connected.
859 */
860 if (motg->chg_type == USB_SDP_CHARGER)
861 msm_otg_notify_charger(motg, mA);
862
863 return 0;
864}
865
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530866static void msm_otg_start_host(struct otg_transceiver *otg, int on)
867{
868 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
869 struct msm_otg_platform_data *pdata = motg->pdata;
870 struct usb_hcd *hcd;
871
872 if (!otg->host)
873 return;
874
875 hcd = bus_to_hcd(otg->host);
876
877 if (on) {
878 dev_dbg(otg->dev, "host on\n");
879
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530880 /*
881 * Some boards have a switch cotrolled by gpio
882 * to enable/disable internal HUB. Enable internal
883 * HUB before kicking the host.
884 */
885 if (pdata->setup_gpio)
886 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530887 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530888 } else {
889 dev_dbg(otg->dev, "host off\n");
890
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530891 usb_remove_hcd(hcd);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530892 /* HCD core reset all bits of PORTSC. select ULPI phy */
893 writel_relaxed(0x80000000, USB_PORTSC);
894
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530895 if (pdata->setup_gpio)
896 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530897 }
898}
899
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700900static int msm_otg_usbdev_notify(struct notifier_block *self,
901 unsigned long action, void *priv)
902{
903 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530904 struct usb_device *udev = priv;
905
906 if (!aca_enabled())
907 goto out;
908
909 if (action == USB_BUS_ADD || action == USB_BUS_REMOVE)
910 goto out;
911
912 if (udev->bus != motg->otg.host)
913 goto out;
914 /*
915 * Interested in devices connected directly to the root hub.
916 * ACA dock can supply IDEV_CHG irrespective devices connected
917 * on the accessory port.
918 */
919 if (!udev->parent || udev->parent->parent ||
920 motg->chg_type == USB_ACA_DOCK_CHARGER)
921 goto out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700922
923 switch (action) {
924 case USB_DEVICE_ADD:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530925 usb_disable_autosuspend(udev);
926 /* fall through */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700927 case USB_DEVICE_CONFIG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700928 if (udev->actconfig)
929 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
930 else
931 motg->mA_port = IUNIT;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530932 break;
933 case USB_DEVICE_REMOVE:
934 motg->mA_port = IUNIT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700935 break;
936 default:
937 break;
938 }
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530939 if (test_bit(ID_A, &motg->inputs))
940 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX -
941 motg->mA_port);
942out:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700943 return NOTIFY_OK;
944}
945
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530946static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
947{
948 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
949 struct usb_hcd *hcd;
950
951 /*
952 * Fail host registration if this board can support
953 * only peripheral configuration.
954 */
955 if (motg->pdata->mode == USB_PERIPHERAL) {
956 dev_info(otg->dev, "Host mode is not supported\n");
957 return -ENODEV;
958 }
959
960 if (!host) {
961 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530962 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700963 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530964 msm_otg_start_host(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700965 if (motg->pdata->vbus_power)
966 motg->pdata->vbus_power(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530967 otg->host = NULL;
968 otg->state = OTG_STATE_UNDEFINED;
969 schedule_work(&motg->sm_work);
970 } else {
971 otg->host = NULL;
972 }
973
974 return 0;
975 }
976
977 hcd = bus_to_hcd(host);
978 hcd->power_budget = motg->pdata->power_budget;
979
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700980 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
981 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530982 otg->host = host;
983 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
984
985 /*
986 * Kick the state machine work, if peripheral is not supported
987 * or peripheral is already registered with us.
988 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530989 if (motg->pdata->mode == USB_HOST || otg->gadget) {
990 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530991 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530992 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530993
994 return 0;
995}
996
997static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
998{
999 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1000 struct msm_otg_platform_data *pdata = motg->pdata;
1001
1002 if (!otg->gadget)
1003 return;
1004
1005 if (on) {
1006 dev_dbg(otg->dev, "gadget on\n");
1007 /*
1008 * Some boards have a switch cotrolled by gpio
1009 * to enable/disable internal HUB. Disable internal
1010 * HUB before kicking the gadget.
1011 */
1012 if (pdata->setup_gpio)
1013 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05301014 /*
1015 * vote for minimum dma_latency to prevent idle
1016 * power collapse(pc) while running in peripheral mode.
1017 */
1018 otg_pm_qos_update_latency(motg, 1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301019 usb_gadget_vbus_connect(otg->gadget);
1020 } else {
1021 dev_dbg(otg->dev, "gadget off\n");
1022 usb_gadget_vbus_disconnect(otg->gadget);
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05301023 otg_pm_qos_update_latency(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301024 if (pdata->setup_gpio)
1025 pdata->setup_gpio(OTG_STATE_UNDEFINED);
1026 }
1027
1028}
1029
1030static int msm_otg_set_peripheral(struct otg_transceiver *otg,
1031 struct usb_gadget *gadget)
1032{
1033 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1034
1035 /*
1036 * Fail peripheral registration if this board can support
1037 * only host configuration.
1038 */
1039 if (motg->pdata->mode == USB_HOST) {
1040 dev_info(otg->dev, "Peripheral mode is not supported\n");
1041 return -ENODEV;
1042 }
1043
1044 if (!gadget) {
1045 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301046 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301047 msm_otg_start_peripheral(otg, 0);
1048 otg->gadget = NULL;
1049 otg->state = OTG_STATE_UNDEFINED;
1050 schedule_work(&motg->sm_work);
1051 } else {
1052 otg->gadget = NULL;
1053 }
1054
1055 return 0;
1056 }
1057 otg->gadget = gadget;
1058 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
1059
1060 /*
1061 * Kick the state machine work, if host is not supported
1062 * or host is already registered with us.
1063 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301064 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
1065 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301066 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301067 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301068
1069 return 0;
1070}
1071
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001072static bool msm_chg_aca_detect(struct msm_otg *motg)
1073{
1074 struct otg_transceiver *otg = &motg->otg;
1075 u32 int_sts;
1076 bool ret = false;
1077
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301078 if (!aca_enabled())
1079 goto out;
1080
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001081 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
1082 goto out;
1083
1084 int_sts = ulpi_read(otg, 0x87);
1085 switch (int_sts & 0x1C) {
1086 case 0x08:
1087 if (!test_and_set_bit(ID_A, &motg->inputs)) {
1088 dev_dbg(otg->dev, "ID_A\n");
1089 motg->chg_type = USB_ACA_A_CHARGER;
1090 motg->chg_state = USB_CHG_STATE_DETECTED;
1091 clear_bit(ID_B, &motg->inputs);
1092 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301093 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001094 ret = true;
1095 }
1096 break;
1097 case 0x0C:
1098 if (!test_and_set_bit(ID_B, &motg->inputs)) {
1099 dev_dbg(otg->dev, "ID_B\n");
1100 motg->chg_type = USB_ACA_B_CHARGER;
1101 motg->chg_state = USB_CHG_STATE_DETECTED;
1102 clear_bit(ID_A, &motg->inputs);
1103 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301104 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001105 ret = true;
1106 }
1107 break;
1108 case 0x10:
1109 if (!test_and_set_bit(ID_C, &motg->inputs)) {
1110 dev_dbg(otg->dev, "ID_C\n");
1111 motg->chg_type = USB_ACA_C_CHARGER;
1112 motg->chg_state = USB_CHG_STATE_DETECTED;
1113 clear_bit(ID_A, &motg->inputs);
1114 clear_bit(ID_B, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301115 set_bit(ID, &motg->inputs);
1116 ret = true;
1117 }
1118 break;
1119 case 0x04:
1120 if (test_and_clear_bit(ID, &motg->inputs)) {
1121 dev_dbg(otg->dev, "ID_GND\n");
1122 motg->chg_type = USB_INVALID_CHARGER;
1123 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1124 clear_bit(ID_A, &motg->inputs);
1125 clear_bit(ID_B, &motg->inputs);
1126 clear_bit(ID_C, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001127 ret = true;
1128 }
1129 break;
1130 default:
1131 ret = test_and_clear_bit(ID_A, &motg->inputs) |
1132 test_and_clear_bit(ID_B, &motg->inputs) |
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301133 test_and_clear_bit(ID_C, &motg->inputs) |
1134 !test_and_set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001135 if (ret) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301136 dev_dbg(otg->dev, "ID A/B/C/GND is no more\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001137 motg->chg_type = USB_INVALID_CHARGER;
1138 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1139 }
1140 }
1141out:
1142 return ret;
1143}
1144
1145static void msm_chg_enable_aca_det(struct msm_otg *motg)
1146{
1147 struct otg_transceiver *otg = &motg->otg;
1148
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301149 if (!aca_enabled())
1150 return;
1151
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001152 switch (motg->pdata->phy_type) {
1153 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301154 /* Disable ID_GND in link and PHY */
1155 writel_relaxed(readl_relaxed(USB_OTGSC) & ~(OTGSC_IDPU |
1156 OTGSC_IDIE), USB_OTGSC);
1157 ulpi_write(otg, 0x01, 0x0C);
1158 ulpi_write(otg, 0x10, 0x0F);
1159 ulpi_write(otg, 0x10, 0x12);
1160 /* Enable ACA ID detection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001161 ulpi_write(otg, 0x20, 0x85);
1162 break;
1163 default:
1164 break;
1165 }
1166}
1167
1168static void msm_chg_enable_aca_intr(struct msm_otg *motg)
1169{
1170 struct otg_transceiver *otg = &motg->otg;
1171
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301172 if (!aca_enabled())
1173 return;
1174
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001175 switch (motg->pdata->phy_type) {
1176 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301177 /* Enable ACA Detection interrupt (on any RID change) */
1178 ulpi_write(otg, 0x01, 0x94);
1179 break;
1180 default:
1181 break;
1182 }
1183}
1184
1185static void msm_chg_disable_aca_intr(struct msm_otg *motg)
1186{
1187 struct otg_transceiver *otg = &motg->otg;
1188
1189 if (!aca_enabled())
1190 return;
1191
1192 switch (motg->pdata->phy_type) {
1193 case SNPS_28NM_INTEGRATED_PHY:
1194 ulpi_write(otg, 0x01, 0x95);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001195 break;
1196 default:
1197 break;
1198 }
1199}
1200
1201static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1202{
1203 struct otg_transceiver *otg = &motg->otg;
1204 bool ret = false;
1205
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301206 if (!aca_enabled())
1207 return ret;
1208
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001209 switch (motg->pdata->phy_type) {
1210 case SNPS_28NM_INTEGRATED_PHY:
1211 if (ulpi_read(otg, 0x91) & 1) {
1212 dev_dbg(otg->dev, "RID change\n");
1213 ulpi_write(otg, 0x01, 0x92);
1214 ret = msm_chg_aca_detect(motg);
1215 }
1216 default:
1217 break;
1218 }
1219 return ret;
1220}
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301221
1222static void msm_otg_id_timer_func(unsigned long data)
1223{
1224 struct msm_otg *motg = (struct msm_otg *) data;
1225
1226 if (!aca_enabled())
1227 return;
1228
1229 if (atomic_read(&motg->in_lpm)) {
1230 dev_dbg(motg->otg.dev, "timer: in lpm\n");
1231 return;
1232 }
1233
1234 if (msm_chg_check_aca_intr(motg)) {
1235 dev_dbg(motg->otg.dev, "timer: aca work\n");
1236 schedule_work(&motg->sm_work);
1237 }
1238
1239 if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs))
1240 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
1241}
1242
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301243static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1244{
1245 struct otg_transceiver *otg = &motg->otg;
1246 u32 chg_det;
1247 bool ret = false;
1248
1249 switch (motg->pdata->phy_type) {
1250 case CI_45NM_INTEGRATED_PHY:
1251 chg_det = ulpi_read(otg, 0x34);
1252 ret = chg_det & (1 << 4);
1253 break;
1254 case SNPS_28NM_INTEGRATED_PHY:
1255 chg_det = ulpi_read(otg, 0x87);
1256 ret = chg_det & 1;
1257 break;
1258 default:
1259 break;
1260 }
1261 return ret;
1262}
1263
1264static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1265{
1266 struct otg_transceiver *otg = &motg->otg;
1267 u32 chg_det;
1268
1269 switch (motg->pdata->phy_type) {
1270 case CI_45NM_INTEGRATED_PHY:
1271 chg_det = ulpi_read(otg, 0x34);
1272 /* Turn off charger block */
1273 chg_det |= ~(1 << 1);
1274 ulpi_write(otg, chg_det, 0x34);
1275 udelay(20);
1276 /* control chg block via ULPI */
1277 chg_det &= ~(1 << 3);
1278 ulpi_write(otg, chg_det, 0x34);
1279 /* put it in host mode for enabling D- source */
1280 chg_det &= ~(1 << 2);
1281 ulpi_write(otg, chg_det, 0x34);
1282 /* Turn on chg detect block */
1283 chg_det &= ~(1 << 1);
1284 ulpi_write(otg, chg_det, 0x34);
1285 udelay(20);
1286 /* enable chg detection */
1287 chg_det &= ~(1 << 0);
1288 ulpi_write(otg, chg_det, 0x34);
1289 break;
1290 case SNPS_28NM_INTEGRATED_PHY:
1291 /*
1292 * Configure DM as current source, DP as current sink
1293 * and enable battery charging comparators.
1294 */
1295 ulpi_write(otg, 0x8, 0x85);
1296 ulpi_write(otg, 0x2, 0x85);
1297 ulpi_write(otg, 0x1, 0x85);
1298 break;
1299 default:
1300 break;
1301 }
1302}
1303
1304static bool msm_chg_check_primary_det(struct msm_otg *motg)
1305{
1306 struct otg_transceiver *otg = &motg->otg;
1307 u32 chg_det;
1308 bool ret = false;
1309
1310 switch (motg->pdata->phy_type) {
1311 case CI_45NM_INTEGRATED_PHY:
1312 chg_det = ulpi_read(otg, 0x34);
1313 ret = chg_det & (1 << 4);
1314 break;
1315 case SNPS_28NM_INTEGRATED_PHY:
1316 chg_det = ulpi_read(otg, 0x87);
1317 ret = chg_det & 1;
1318 break;
1319 default:
1320 break;
1321 }
1322 return ret;
1323}
1324
1325static void msm_chg_enable_primary_det(struct msm_otg *motg)
1326{
1327 struct otg_transceiver *otg = &motg->otg;
1328 u32 chg_det;
1329
1330 switch (motg->pdata->phy_type) {
1331 case CI_45NM_INTEGRATED_PHY:
1332 chg_det = ulpi_read(otg, 0x34);
1333 /* enable chg detection */
1334 chg_det &= ~(1 << 0);
1335 ulpi_write(otg, chg_det, 0x34);
1336 break;
1337 case SNPS_28NM_INTEGRATED_PHY:
1338 /*
1339 * Configure DP as current source, DM as current sink
1340 * and enable battery charging comparators.
1341 */
1342 ulpi_write(otg, 0x2, 0x85);
1343 ulpi_write(otg, 0x1, 0x85);
1344 break;
1345 default:
1346 break;
1347 }
1348}
1349
1350static bool msm_chg_check_dcd(struct msm_otg *motg)
1351{
1352 struct otg_transceiver *otg = &motg->otg;
1353 u32 line_state;
1354 bool ret = false;
1355
1356 switch (motg->pdata->phy_type) {
1357 case CI_45NM_INTEGRATED_PHY:
1358 line_state = ulpi_read(otg, 0x15);
1359 ret = !(line_state & 1);
1360 break;
1361 case SNPS_28NM_INTEGRATED_PHY:
1362 line_state = ulpi_read(otg, 0x87);
1363 ret = line_state & 2;
1364 break;
1365 default:
1366 break;
1367 }
1368 return ret;
1369}
1370
1371static void msm_chg_disable_dcd(struct msm_otg *motg)
1372{
1373 struct otg_transceiver *otg = &motg->otg;
1374 u32 chg_det;
1375
1376 switch (motg->pdata->phy_type) {
1377 case CI_45NM_INTEGRATED_PHY:
1378 chg_det = ulpi_read(otg, 0x34);
1379 chg_det &= ~(1 << 5);
1380 ulpi_write(otg, chg_det, 0x34);
1381 break;
1382 case SNPS_28NM_INTEGRATED_PHY:
1383 ulpi_write(otg, 0x10, 0x86);
1384 break;
1385 default:
1386 break;
1387 }
1388}
1389
1390static void msm_chg_enable_dcd(struct msm_otg *motg)
1391{
1392 struct otg_transceiver *otg = &motg->otg;
1393 u32 chg_det;
1394
1395 switch (motg->pdata->phy_type) {
1396 case CI_45NM_INTEGRATED_PHY:
1397 chg_det = ulpi_read(otg, 0x34);
1398 /* Turn on D+ current source */
1399 chg_det |= (1 << 5);
1400 ulpi_write(otg, chg_det, 0x34);
1401 break;
1402 case SNPS_28NM_INTEGRATED_PHY:
1403 /* Data contact detection enable */
1404 ulpi_write(otg, 0x10, 0x85);
1405 break;
1406 default:
1407 break;
1408 }
1409}
1410
1411static void msm_chg_block_on(struct msm_otg *motg)
1412{
1413 struct otg_transceiver *otg = &motg->otg;
1414 u32 func_ctrl, chg_det;
1415
1416 /* put the controller in non-driving mode */
1417 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1418 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1419 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1420 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1421
1422 switch (motg->pdata->phy_type) {
1423 case CI_45NM_INTEGRATED_PHY:
1424 chg_det = ulpi_read(otg, 0x34);
1425 /* control chg block via ULPI */
1426 chg_det &= ~(1 << 3);
1427 ulpi_write(otg, chg_det, 0x34);
1428 /* Turn on chg detect block */
1429 chg_det &= ~(1 << 1);
1430 ulpi_write(otg, chg_det, 0x34);
1431 udelay(20);
1432 break;
1433 case SNPS_28NM_INTEGRATED_PHY:
1434 /* Clear charger detecting control bits */
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301435 ulpi_write(otg, 0x1F, 0x86);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301436 /* Clear alt interrupt latch and enable bits */
1437 ulpi_write(otg, 0x1F, 0x92);
1438 ulpi_write(otg, 0x1F, 0x95);
1439 udelay(100);
1440 break;
1441 default:
1442 break;
1443 }
1444}
1445
1446static void msm_chg_block_off(struct msm_otg *motg)
1447{
1448 struct otg_transceiver *otg = &motg->otg;
1449 u32 func_ctrl, chg_det;
1450
1451 switch (motg->pdata->phy_type) {
1452 case CI_45NM_INTEGRATED_PHY:
1453 chg_det = ulpi_read(otg, 0x34);
1454 /* Turn off charger block */
1455 chg_det |= ~(1 << 1);
1456 ulpi_write(otg, chg_det, 0x34);
1457 break;
1458 case SNPS_28NM_INTEGRATED_PHY:
1459 /* Clear charger detecting control bits */
1460 ulpi_write(otg, 0x3F, 0x86);
1461 /* Clear alt interrupt latch and enable bits */
1462 ulpi_write(otg, 0x1F, 0x92);
1463 ulpi_write(otg, 0x1F, 0x95);
1464 break;
1465 default:
1466 break;
1467 }
1468
1469 /* put the controller in normal mode */
1470 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1471 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1472 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1473 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1474}
1475
Anji jonnalad270e2d2011-08-09 11:28:32 +05301476static const char *chg_to_string(enum usb_chg_type chg_type)
1477{
1478 switch (chg_type) {
1479 case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
1480 case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
1481 case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
1482 case USB_ACA_A_CHARGER: return "USB_ACA_A_CHARGER";
1483 case USB_ACA_B_CHARGER: return "USB_ACA_B_CHARGER";
1484 case USB_ACA_C_CHARGER: return "USB_ACA_C_CHARGER";
1485 case USB_ACA_DOCK_CHARGER: return "USB_ACA_DOCK_CHARGER";
1486 default: return "INVALID_CHARGER";
1487 }
1488}
1489
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301490#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1491#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
1492#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
1493#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
1494static void msm_chg_detect_work(struct work_struct *w)
1495{
1496 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1497 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001498 bool is_dcd, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301499 unsigned long delay;
1500
1501 dev_dbg(otg->dev, "chg detection work\n");
1502 switch (motg->chg_state) {
1503 case USB_CHG_STATE_UNDEFINED:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301504 msm_chg_block_on(motg);
1505 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001506 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301507 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1508 motg->dcd_retries = 0;
1509 delay = MSM_CHG_DCD_POLL_TIME;
1510 break;
1511 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001512 is_aca = msm_chg_aca_detect(motg);
1513 if (is_aca) {
1514 /*
1515 * ID_A can be ACA dock too. continue
1516 * primary detection after DCD.
1517 */
1518 if (test_bit(ID_A, &motg->inputs)) {
1519 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1520 } else {
1521 delay = 0;
1522 break;
1523 }
1524 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301525 is_dcd = msm_chg_check_dcd(motg);
1526 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1527 if (is_dcd || tmout) {
1528 msm_chg_disable_dcd(motg);
1529 msm_chg_enable_primary_det(motg);
1530 delay = MSM_CHG_PRIMARY_DET_TIME;
1531 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1532 } else {
1533 delay = MSM_CHG_DCD_POLL_TIME;
1534 }
1535 break;
1536 case USB_CHG_STATE_DCD_DONE:
1537 vout = msm_chg_check_primary_det(motg);
1538 if (vout) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301539 if (test_bit(ID_A, &motg->inputs)) {
1540 motg->chg_type = USB_ACA_DOCK_CHARGER;
1541 motg->chg_state = USB_CHG_STATE_DETECTED;
1542 delay = 0;
1543 break;
1544 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301545 msm_chg_enable_secondary_det(motg);
1546 delay = MSM_CHG_SECONDARY_DET_TIME;
1547 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1548 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301549 if (test_bit(ID_A, &motg->inputs)) {
1550 motg->chg_type = USB_ACA_A_CHARGER;
1551 motg->chg_state = USB_CHG_STATE_DETECTED;
1552 delay = 0;
1553 break;
1554 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301555 motg->chg_type = USB_SDP_CHARGER;
1556 motg->chg_state = USB_CHG_STATE_DETECTED;
1557 delay = 0;
1558 }
1559 break;
1560 case USB_CHG_STATE_PRIMARY_DONE:
1561 vout = msm_chg_check_secondary_det(motg);
1562 if (vout)
1563 motg->chg_type = USB_DCP_CHARGER;
1564 else
1565 motg->chg_type = USB_CDP_CHARGER;
1566 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1567 /* fall through */
1568 case USB_CHG_STATE_SECONDARY_DONE:
1569 motg->chg_state = USB_CHG_STATE_DETECTED;
1570 case USB_CHG_STATE_DETECTED:
1571 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001572 msm_chg_enable_aca_det(motg);
1573 msm_chg_enable_aca_intr(motg);
Anji jonnalad270e2d2011-08-09 11:28:32 +05301574 dev_dbg(otg->dev, "chg_type = %s\n",
1575 chg_to_string(motg->chg_type));
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301576 schedule_work(&motg->sm_work);
1577 return;
1578 default:
1579 return;
1580 }
1581
1582 schedule_delayed_work(&motg->chg_work, delay);
1583}
1584
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301585/*
1586 * We support OTG, Peripheral only and Host only configurations. In case
1587 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1588 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1589 * enabled when switch is controlled by user and default mode is supplied
1590 * by board file, which can be changed by userspace later.
1591 */
1592static void msm_otg_init_sm(struct msm_otg *motg)
1593{
1594 struct msm_otg_platform_data *pdata = motg->pdata;
1595 u32 otgsc = readl(USB_OTGSC);
1596
1597 switch (pdata->mode) {
1598 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001599 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301600 if (pdata->default_mode == USB_HOST) {
1601 clear_bit(ID, &motg->inputs);
1602 } else if (pdata->default_mode == USB_PERIPHERAL) {
1603 set_bit(ID, &motg->inputs);
1604 set_bit(B_SESS_VLD, &motg->inputs);
1605 } else {
1606 set_bit(ID, &motg->inputs);
1607 clear_bit(B_SESS_VLD, &motg->inputs);
1608 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001609 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301610 if (aca_enabled()) {
1611 if (irq_read_line(motg->pdata->pmic_id_irq))
1612 set_bit(ID, &motg->inputs);
1613 else
1614 clear_bit(ID, &motg->inputs);
1615
1616 } else {
1617 if (otgsc & OTGSC_ID)
1618 set_bit(ID, &motg->inputs);
1619 else
1620 clear_bit(ID, &motg->inputs);
1621 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001622
1623 if (otgsc & OTGSC_BSV)
1624 set_bit(B_SESS_VLD, &motg->inputs);
1625 else
1626 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301627 }
1628 break;
1629 case USB_HOST:
1630 clear_bit(ID, &motg->inputs);
1631 break;
1632 case USB_PERIPHERAL:
1633 set_bit(ID, &motg->inputs);
1634 if (otgsc & OTGSC_BSV)
1635 set_bit(B_SESS_VLD, &motg->inputs);
1636 else
1637 clear_bit(B_SESS_VLD, &motg->inputs);
1638 break;
1639 default:
1640 break;
1641 }
1642}
1643
1644static void msm_otg_sm_work(struct work_struct *w)
1645{
1646 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
1647 struct otg_transceiver *otg = &motg->otg;
1648
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301649 pm_runtime_resume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301650 switch (otg->state) {
1651 case OTG_STATE_UNDEFINED:
1652 dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
1653 msm_otg_reset(otg);
1654 msm_otg_init_sm(motg);
1655 otg->state = OTG_STATE_B_IDLE;
1656 /* FALL THROUGH */
1657 case OTG_STATE_B_IDLE:
1658 dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001659 if ((!test_bit(ID, &motg->inputs) ||
1660 test_bit(ID_A, &motg->inputs)) && otg->host) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001661 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
1662 msm_otg_notify_charger(motg,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301663 IDEV_ACA_CHG_MAX);
1664 else if (test_bit(ID_A, &motg->inputs))
1665 msm_otg_notify_charger(motg,
1666 IDEV_ACA_CHG_MAX - IUNIT);
1667 else if (motg->pdata->vbus_power)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001668 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301669 msm_otg_start_host(otg, 1);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301670 /*
1671 * Link can not generate PHY_ALT interrupt
1672 * in host mode when no device is attached
1673 * to the port. It is also observed PHY_ALT
1674 * interrupt missing upon Micro-A cable disconnect.
1675 * Hence disable PHY_ALT interrupt and perform
1676 * polling to detect RID change.
1677 */
1678 msm_chg_enable_aca_det(motg);
1679 msm_chg_disable_aca_intr(motg);
1680 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301681 otg->state = OTG_STATE_A_HOST;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301682 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1683 switch (motg->chg_state) {
1684 case USB_CHG_STATE_UNDEFINED:
1685 msm_chg_detect_work(&motg->chg_work.work);
1686 break;
1687 case USB_CHG_STATE_DETECTED:
1688 switch (motg->chg_type) {
1689 case USB_DCP_CHARGER:
1690 msm_otg_notify_charger(motg,
1691 IDEV_CHG_MAX);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301692 pm_runtime_put_noidle(otg->dev);
1693 pm_runtime_suspend(otg->dev);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301694 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301695 case USB_ACA_B_CHARGER:
1696 msm_otg_notify_charger(motg,
1697 IDEV_ACA_CHG_MAX);
1698 /*
1699 * (ID_B --> ID_C) PHY_ALT interrupt can
1700 * not be detected in LPM.
1701 */
1702 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301703 case USB_CDP_CHARGER:
1704 msm_otg_notify_charger(motg,
1705 IDEV_CHG_MAX);
1706 msm_otg_start_peripheral(otg, 1);
1707 otg->state = OTG_STATE_B_PERIPHERAL;
1708 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301709 case USB_ACA_C_CHARGER:
1710 msm_otg_notify_charger(motg,
1711 IDEV_ACA_CHG_MAX);
1712 msm_otg_start_peripheral(otg, 1);
1713 otg->state = OTG_STATE_B_PERIPHERAL;
1714 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301715 case USB_SDP_CHARGER:
1716 msm_otg_notify_charger(motg, IUNIT);
1717 msm_otg_start_peripheral(otg, 1);
1718 otg->state = OTG_STATE_B_PERIPHERAL;
1719 break;
1720 default:
1721 break;
1722 }
1723 break;
1724 default:
1725 break;
1726 }
1727 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301728 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301729 msm_otg_notify_charger(motg, 0);
1730 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1731 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301732 msm_otg_reset(otg);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301733 pm_runtime_put_noidle(otg->dev);
1734 pm_runtime_suspend(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301735 }
1736 break;
1737 case OTG_STATE_B_PERIPHERAL:
1738 dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
1739 if (!test_bit(B_SESS_VLD, &motg->inputs) ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001740 !test_bit(ID, &motg->inputs) ||
1741 !test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301742 msm_otg_start_peripheral(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001743 otg->state = OTG_STATE_B_IDLE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001744 schedule_work(w);
1745 } else if (test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301746 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001747 }
1748 break;
1749 case OTG_STATE_A_HOST:
1750 dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
1751 if (test_bit(ID, &motg->inputs) &&
1752 !test_bit(ID_A, &motg->inputs)) {
1753 msm_otg_start_host(otg, 0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301754 if (motg->pdata->vbus_power) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001755 motg->pdata->vbus_power(0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301756 msleep(100); /* TA_WAIT_VFALL */
1757 }
1758 /*
1759 * Exit point of host mode.
1760 *
1761 * 1. Micro-A cable disconnect: Just schedule
1762 * the work. PHY is reset in B_IDLE and LPM
1763 * is allowed.
1764 * 2. ID_GND --> ID_B: No need to reset the PHY.
1765 * HCD core clears all PORTSC bits and initializes
1766 * the controller to host mode in remove_hcd.
1767 * Restore PORTSC transceiver select bits (ULPI)
1768 * and reset the controller to change MODE bits.
1769 * PHY_ALT interrupt can not occur in host mode.
1770 */
1771 del_timer_sync(&motg->id_timer);
1772 if (motg->chg_state != USB_CHG_STATE_UNDEFINED) {
1773 msm_otg_link_reset(motg);
1774 msm_chg_enable_aca_intr(motg);
1775 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301776 otg->state = OTG_STATE_B_IDLE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301777 schedule_work(w);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001778 } else if (test_bit(ID_A, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001779 if (motg->pdata->vbus_power)
1780 motg->pdata->vbus_power(0);
1781 msm_otg_notify_charger(motg,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301782 IDEV_ACA_CHG_MAX - motg->mA_port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001783 } else if (!test_bit(ID, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001784 msm_otg_notify_charger(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785 if (motg->pdata->vbus_power)
1786 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301787 }
1788 break;
1789 default:
1790 break;
1791 }
1792}
1793
1794static irqreturn_t msm_otg_irq(int irq, void *data)
1795{
1796 struct msm_otg *motg = data;
1797 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001798 u32 otgsc = 0, usbsts;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301799
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301800 if (atomic_read(&motg->in_lpm)) {
1801 disable_irq_nosync(irq);
1802 motg->async_int = 1;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301803 pm_request_resume(otg->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301804 return IRQ_HANDLED;
1805 }
1806
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001807 usbsts = readl(USB_USBSTS);
1808 if ((usbsts & PHY_ALT_INT)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301809 dev_dbg(otg->dev, "PHY_ALT interrupt\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001810 writel(PHY_ALT_INT, USB_USBSTS);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301811 if (msm_chg_check_aca_intr(motg)) {
1812 dev_dbg(otg->dev, "ACA work from IRQ\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001813 schedule_work(&motg->sm_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301814 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001815 return IRQ_HANDLED;
1816 }
1817
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301818 otgsc = readl(USB_OTGSC);
1819 if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1820 return IRQ_NONE;
1821
1822 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301823 if (otgsc & OTGSC_ID) {
1824 dev_dbg(otg->dev, "ID set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301825 set_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301826 } else {
1827 dev_dbg(otg->dev, "ID clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301828 clear_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301829 msm_chg_enable_aca_det(motg);
1830 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001831 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301832 } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301833 if (otgsc & OTGSC_BSV) {
1834 dev_dbg(otg->dev, "BSV set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301835 set_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301836 } else {
1837 dev_dbg(otg->dev, "BSV clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301838 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301839 msm_chg_check_aca_intr(motg);
1840 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001841 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301842 }
1843
1844 writel(otgsc, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001845 return IRQ_HANDLED;
1846}
1847
1848static void msm_otg_set_vbus_state(int online)
1849{
1850 struct msm_otg *motg = the_msm_otg;
1851
1852 /* We depend on PMIC for only VBUS ON interrupt */
1853 if (!atomic_read(&motg->in_lpm) || !online)
1854 return;
1855
1856 /*
1857 * Let interrupt handler take care of resuming
1858 * the hardware.
1859 */
1860 msm_otg_irq(motg->irq, (void *) motg);
1861}
1862
1863static irqreturn_t msm_pmic_id_irq(int irq, void *data)
1864{
1865 struct msm_otg *motg = data;
1866
1867 if (atomic_read(&motg->in_lpm) && !motg->async_int)
1868 msm_otg_irq(motg->irq, motg);
1869
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301870 return IRQ_HANDLED;
1871}
1872
1873static int msm_otg_mode_show(struct seq_file *s, void *unused)
1874{
1875 struct msm_otg *motg = s->private;
1876 struct otg_transceiver *otg = &motg->otg;
1877
1878 switch (otg->state) {
1879 case OTG_STATE_A_HOST:
1880 seq_printf(s, "host\n");
1881 break;
1882 case OTG_STATE_B_PERIPHERAL:
1883 seq_printf(s, "peripheral\n");
1884 break;
1885 default:
1886 seq_printf(s, "none\n");
1887 break;
1888 }
1889
1890 return 0;
1891}
1892
1893static int msm_otg_mode_open(struct inode *inode, struct file *file)
1894{
1895 return single_open(file, msm_otg_mode_show, inode->i_private);
1896}
1897
1898static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1899 size_t count, loff_t *ppos)
1900{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05301901 struct seq_file *s = file->private_data;
1902 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301903 char buf[16];
1904 struct otg_transceiver *otg = &motg->otg;
1905 int status = count;
1906 enum usb_mode_type req_mode;
1907
1908 memset(buf, 0x00, sizeof(buf));
1909
1910 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1911 status = -EFAULT;
1912 goto out;
1913 }
1914
1915 if (!strncmp(buf, "host", 4)) {
1916 req_mode = USB_HOST;
1917 } else if (!strncmp(buf, "peripheral", 10)) {
1918 req_mode = USB_PERIPHERAL;
1919 } else if (!strncmp(buf, "none", 4)) {
1920 req_mode = USB_NONE;
1921 } else {
1922 status = -EINVAL;
1923 goto out;
1924 }
1925
1926 switch (req_mode) {
1927 case USB_NONE:
1928 switch (otg->state) {
1929 case OTG_STATE_A_HOST:
1930 case OTG_STATE_B_PERIPHERAL:
1931 set_bit(ID, &motg->inputs);
1932 clear_bit(B_SESS_VLD, &motg->inputs);
1933 break;
1934 default:
1935 goto out;
1936 }
1937 break;
1938 case USB_PERIPHERAL:
1939 switch (otg->state) {
1940 case OTG_STATE_B_IDLE:
1941 case OTG_STATE_A_HOST:
1942 set_bit(ID, &motg->inputs);
1943 set_bit(B_SESS_VLD, &motg->inputs);
1944 break;
1945 default:
1946 goto out;
1947 }
1948 break;
1949 case USB_HOST:
1950 switch (otg->state) {
1951 case OTG_STATE_B_IDLE:
1952 case OTG_STATE_B_PERIPHERAL:
1953 clear_bit(ID, &motg->inputs);
1954 break;
1955 default:
1956 goto out;
1957 }
1958 break;
1959 default:
1960 goto out;
1961 }
1962
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301963 pm_runtime_resume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301964 schedule_work(&motg->sm_work);
1965out:
1966 return status;
1967}
1968
1969const struct file_operations msm_otg_mode_fops = {
1970 .open = msm_otg_mode_open,
1971 .read = seq_read,
1972 .write = msm_otg_mode_write,
1973 .llseek = seq_lseek,
1974 .release = single_release,
1975};
1976
Anji jonnalad270e2d2011-08-09 11:28:32 +05301977static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
1978{
1979 struct msm_otg *motg = s->private;
1980
1981 seq_printf(s, chg_to_string(motg->chg_type));
1982 return 0;
1983}
1984
1985static int msm_otg_chg_open(struct inode *inode, struct file *file)
1986{
1987 return single_open(file, msm_otg_show_chg_type, inode->i_private);
1988}
1989
1990const struct file_operations msm_otg_chg_fops = {
1991 .open = msm_otg_chg_open,
1992 .read = seq_read,
1993 .llseek = seq_lseek,
1994 .release = single_release,
1995};
1996
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301997static int msm_otg_aca_show(struct seq_file *s, void *unused)
1998{
1999 if (debug_aca_enabled)
2000 seq_printf(s, "enabled\n");
2001 else
2002 seq_printf(s, "disabled\n");
2003
2004 return 0;
2005}
2006
2007static int msm_otg_aca_open(struct inode *inode, struct file *file)
2008{
2009 return single_open(file, msm_otg_aca_show, inode->i_private);
2010}
2011
2012static ssize_t msm_otg_aca_write(struct file *file, const char __user *ubuf,
2013 size_t count, loff_t *ppos)
2014{
2015 char buf[8];
2016
2017 memset(buf, 0x00, sizeof(buf));
2018
2019 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
2020 return -EFAULT;
2021
2022 if (!strncmp(buf, "enable", 6))
2023 debug_aca_enabled = true;
2024 else
2025 debug_aca_enabled = false;
2026
2027 return count;
2028}
2029
2030const struct file_operations msm_otg_aca_fops = {
2031 .open = msm_otg_aca_open,
2032 .read = seq_read,
2033 .write = msm_otg_aca_write,
2034 .llseek = seq_lseek,
2035 .release = single_release,
2036};
2037
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302038static struct dentry *msm_otg_dbg_root;
2039static struct dentry *msm_otg_dbg_mode;
Anji jonnalad270e2d2011-08-09 11:28:32 +05302040static struct dentry *msm_otg_chg_type;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302041static struct dentry *msm_otg_dbg_aca;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302042
2043static int msm_otg_debugfs_init(struct msm_otg *motg)
2044{
Anji jonnalad270e2d2011-08-09 11:28:32 +05302045
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302046 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
2047
2048 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
2049 return -ENODEV;
2050
Anji jonnalad270e2d2011-08-09 11:28:32 +05302051 if (motg->pdata->mode == USB_OTG &&
2052 motg->pdata->otg_control == OTG_USER_CONTROL) {
2053
2054 msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
2055 S_IWUSR, msm_otg_dbg_root, motg,
2056 &msm_otg_mode_fops);
2057
2058 if (!msm_otg_dbg_mode) {
2059 debugfs_remove(msm_otg_dbg_root);
2060 msm_otg_dbg_root = NULL;
2061 return -ENODEV;
2062 }
2063 }
2064
2065 msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
2066 msm_otg_dbg_root, motg,
2067 &msm_otg_chg_fops);
2068
2069 if (!msm_otg_chg_type) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302070 debugfs_remove_recursive(msm_otg_dbg_root);
2071 return -ENODEV;
2072 }
2073
2074 msm_otg_dbg_aca = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
2075 msm_otg_dbg_root, motg,
2076 &msm_otg_aca_fops);
2077
2078 if (!msm_otg_dbg_aca) {
2079 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302080 return -ENODEV;
2081 }
2082
2083 return 0;
2084}
2085
2086static void msm_otg_debugfs_cleanup(void)
2087{
Anji jonnalad270e2d2011-08-09 11:28:32 +05302088 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302089}
2090
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302091static u64 msm_otg_dma_mask = DMA_BIT_MASK(64);
2092static struct platform_device *msm_otg_add_pdev(
2093 struct platform_device *ofdev, const char *name)
2094{
2095 struct platform_device *pdev;
2096 const struct resource *res = ofdev->resource;
2097 unsigned int num = ofdev->num_resources;
2098 int retval;
2099
2100 pdev = platform_device_alloc(name, -1);
2101 if (!pdev) {
2102 retval = -ENOMEM;
2103 goto error;
2104 }
2105
2106 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
2107 pdev->dev.dma_mask = &msm_otg_dma_mask;
2108
2109 if (num) {
2110 retval = platform_device_add_resources(pdev, res, num);
2111 if (retval)
2112 goto error;
2113 }
2114
2115 retval = platform_device_add(pdev);
2116 if (retval)
2117 goto error;
2118
2119 return pdev;
2120
2121error:
2122 platform_device_put(pdev);
2123 return ERR_PTR(retval);
2124}
2125
2126static int msm_otg_setup_devices(struct platform_device *ofdev,
2127 enum usb_mode_type mode, bool init)
2128{
2129 const char *gadget_name = "msm_hsusb";
2130 const char *host_name = "msm_hsusb_host";
2131 static struct platform_device *gadget_pdev;
2132 static struct platform_device *host_pdev;
2133 int retval = 0;
2134
2135 if (!init) {
2136 if (gadget_pdev)
2137 platform_device_unregister(gadget_pdev);
2138 if (host_pdev)
2139 platform_device_unregister(host_pdev);
2140 return 0;
2141 }
2142
2143 switch (mode) {
2144 case USB_OTG:
2145 /* fall through */
2146 case USB_PERIPHERAL:
2147 gadget_pdev = msm_otg_add_pdev(ofdev, gadget_name);
2148 if (IS_ERR(gadget_pdev)) {
2149 retval = PTR_ERR(gadget_pdev);
2150 break;
2151 }
2152 if (mode == USB_PERIPHERAL)
2153 break;
2154 /* fall through */
2155 case USB_HOST:
2156 host_pdev = msm_otg_add_pdev(ofdev, host_name);
2157 if (IS_ERR(host_pdev)) {
2158 retval = PTR_ERR(host_pdev);
2159 if (mode == USB_OTG)
2160 platform_device_unregister(gadget_pdev);
2161 }
2162 break;
2163 default:
2164 break;
2165 }
2166
2167 return retval;
2168}
2169
2170struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
2171{
2172 struct device_node *node = pdev->dev.of_node;
2173 struct msm_otg_platform_data *pdata;
2174 int len = 0;
2175
2176 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
2177 if (!pdata) {
2178 pr_err("unable to allocate platform data\n");
2179 return NULL;
2180 }
2181 of_get_property(node, "qcom,hsusb-otg-phy-init-seq", &len);
2182 if (len) {
2183 pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
2184 if (!pdata->phy_init_seq)
2185 return NULL;
2186 of_property_read_u32_array(node, "qcom,hsusb-otg-phy-init-seq",
2187 pdata->phy_init_seq,
2188 len/sizeof(*pdata->phy_init_seq));
2189 }
2190 of_property_read_u32(node, "qcom,hsusb-otg-power-budget",
2191 &pdata->power_budget);
2192 of_property_read_u32(node, "qcom,hsusb-otg-mode",
2193 &pdata->mode);
2194 of_property_read_u32(node, "qcom,hsusb-otg-otg-control",
2195 &pdata->otg_control);
2196 of_property_read_u32(node, "qcom,hsusb-otg-default-mode",
2197 &pdata->default_mode);
2198 of_property_read_u32(node, "qcom,hsusb-otg-phy-type",
2199 &pdata->phy_type);
2200 of_property_read_u32(node, "qcom,hsusb-otg-pmic-id-irq",
2201 &pdata->pmic_id_irq);
2202 of_property_read_string(node, "qcom,hsusb-otg-pclk-src-name",
2203 &pdata->pclk_src_name);
2204 return pdata;
2205}
2206
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302207static int __init msm_otg_probe(struct platform_device *pdev)
2208{
2209 int ret = 0;
2210 struct resource *res;
2211 struct msm_otg *motg;
2212 struct otg_transceiver *otg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302213 struct msm_otg_platform_data *pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302214
2215 dev_info(&pdev->dev, "msm_otg probe\n");
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302216
2217 if (pdev->dev.of_node) {
2218 dev_dbg(&pdev->dev, "device tree enabled\n");
2219 pdata = msm_otg_dt_to_pdata(pdev);
2220 if (!pdata)
2221 return -ENOMEM;
2222 ret = msm_otg_setup_devices(pdev, pdata->mode, true);
2223 if (ret) {
2224 dev_err(&pdev->dev, "devices setup failed\n");
2225 return ret;
2226 }
2227 } else if (!pdev->dev.platform_data) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302228 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
2229 return -ENODEV;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302230 } else {
2231 pdata = pdev->dev.platform_data;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302232 }
2233
2234 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
2235 if (!motg) {
2236 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
2237 return -ENOMEM;
2238 }
2239
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002240 the_msm_otg = motg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302241 motg->pdata = pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302242 otg = &motg->otg;
2243 otg->dev = &pdev->dev;
2244
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302245 /*
2246 * ACA ID_GND threshold range is overlapped with OTG ID_FLOAT. Hence
2247 * PHY treat ACA ID_GND as float and no interrupt is generated. But
2248 * PMIC can detect ACA ID_GND and generate an interrupt.
2249 */
2250 if (aca_enabled() && motg->pdata->otg_control != OTG_PMIC_CONTROL) {
2251 dev_err(&pdev->dev, "ACA can not be enabled without PMIC\n");
2252 ret = -EINVAL;
2253 goto free_motg;
2254 }
2255
Amit Blay02eff132011-09-21 16:46:24 +03002256 /* Some targets don't support PHY clock. */
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302257 motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
Amit Blay02eff132011-09-21 16:46:24 +03002258 if (IS_ERR(motg->phy_reset_clk))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302259 dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302260
2261 motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
2262 if (IS_ERR(motg->clk)) {
2263 dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
2264 ret = PTR_ERR(motg->clk);
2265 goto put_phy_reset_clk;
2266 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302267 clk_set_rate(motg->clk, 60000000);
2268
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05302269 /* pm qos request to prevent apps idle power collapse */
2270 if (motg->pdata->swfi_latency)
2271 pm_qos_add_request(&motg->pm_qos_req_dma,
2272 PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302273 /*
2274 * If USB Core is running its protocol engine based on CORE CLK,
2275 * CORE CLK must be running at >55Mhz for correct HSUSB
2276 * operation and USB core cannot tolerate frequency changes on
2277 * CORE CLK. For such USB cores, vote for maximum clk frequency
2278 * on pclk source
2279 */
2280 if (motg->pdata->pclk_src_name) {
2281 motg->pclk_src = clk_get(&pdev->dev,
2282 motg->pdata->pclk_src_name);
2283 if (IS_ERR(motg->pclk_src))
2284 goto put_clk;
2285 clk_set_rate(motg->pclk_src, INT_MAX);
2286 clk_enable(motg->pclk_src);
2287 } else
2288 motg->pclk_src = ERR_PTR(-ENOENT);
2289
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302290 motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
2291 if (IS_ERR(motg->pclk)) {
2292 dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
2293 ret = PTR_ERR(motg->pclk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302294 goto put_pclk_src;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302295 }
2296
Amit Blay02eff132011-09-21 16:46:24 +03002297 motg->system_clk = clk_get(&pdev->dev, "usb_hs_system_clk");
2298 if (!IS_ERR(motg->system_clk))
2299 clk_enable(motg->system_clk);
2300
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302301 /*
2302 * USB core clock is not present on all MSM chips. This
2303 * clock is introduced to remove the dependency on AXI
2304 * bus frequency.
2305 */
2306 motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
2307 if (IS_ERR(motg->core_clk))
2308 motg->core_clk = NULL;
2309
2310 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2311 if (!res) {
2312 dev_err(&pdev->dev, "failed to get platform resource mem\n");
2313 ret = -ENODEV;
2314 goto put_core_clk;
2315 }
2316
2317 motg->regs = ioremap(res->start, resource_size(res));
2318 if (!motg->regs) {
2319 dev_err(&pdev->dev, "ioremap failed\n");
2320 ret = -ENOMEM;
2321 goto put_core_clk;
2322 }
2323 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
2324
2325 motg->irq = platform_get_irq(pdev, 0);
2326 if (!motg->irq) {
2327 dev_err(&pdev->dev, "platform_get_irq failed\n");
2328 ret = -ENODEV;
2329 goto free_regs;
2330 }
2331
Anji jonnala7da3f262011-12-02 17:22:14 -08002332 motg->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, "usb");
2333 if (IS_ERR(motg->xo_handle)) {
2334 dev_err(&pdev->dev, "%s not able to get the handle "
2335 "to vote for TCXO D0 buffer\n", __func__);
2336 ret = PTR_ERR(motg->xo_handle);
2337 goto free_regs;
2338 }
2339
2340 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
2341 if (ret) {
2342 dev_err(&pdev->dev, "%s failed to vote for TCXO "
2343 "D0 buffer%d\n", __func__, ret);
2344 goto free_xo_handle;
2345 }
2346
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302347 clk_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302348
2349 ret = msm_hsusb_init_vddcx(motg, 1);
2350 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002351 dev_err(&pdev->dev, "hsusb vddcx init failed\n");
Anji jonnala7da3f262011-12-02 17:22:14 -08002352 goto devote_xo_handle;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302353 }
2354
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002355 ret = msm_hsusb_config_vddcx(1);
2356 if (ret) {
2357 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
2358 goto free_init_vddcx;
2359 }
2360
Anji jonnala11aa5c42011-05-04 10:19:48 +05302361 ret = msm_hsusb_ldo_init(motg, 1);
2362 if (ret) {
2363 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002364 goto free_init_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302365 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002366
2367 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302368 if (ret) {
2369 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002370 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302371 }
2372
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302373 if (motg->core_clk)
2374 clk_enable(motg->core_clk);
2375
2376 writel(0, USB_USBINTR);
2377 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002378 /* Ensure that above STOREs are completed before enabling interrupts */
2379 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302380
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002381 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302382 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302383 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302384 setup_timer(&motg->id_timer, msm_otg_id_timer_func,
2385 (unsigned long) motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302386 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
2387 "msm_otg", motg);
2388 if (ret) {
2389 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002390 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302391 }
2392
2393 otg->init = msm_otg_reset;
2394 otg->set_host = msm_otg_set_host;
2395 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302396 otg->set_power = msm_otg_set_power;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302397 otg->set_suspend = msm_otg_set_suspend;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302398
2399 otg->io_ops = &msm_otg_io_ops;
2400
2401 ret = otg_set_transceiver(&motg->otg);
2402 if (ret) {
2403 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
2404 goto free_irq;
2405 }
2406
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002407 if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
2408 if (motg->pdata->pmic_id_irq) {
2409 ret = request_irq(motg->pdata->pmic_id_irq,
2410 msm_pmic_id_irq,
2411 IRQF_TRIGGER_RISING |
2412 IRQF_TRIGGER_FALLING,
2413 "msm_otg", motg);
2414 if (ret) {
2415 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
2416 goto remove_otg;
2417 }
2418 } else {
2419 ret = -ENODEV;
2420 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
2421 goto remove_otg;
2422 }
2423 }
2424
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302425 msm_hsusb_mhl_switch_enable(motg, 1);
2426
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302427 platform_set_drvdata(pdev, motg);
2428 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002429 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302430
Anji jonnalad270e2d2011-08-09 11:28:32 +05302431 ret = msm_otg_debugfs_init(motg);
2432 if (ret)
2433 dev_dbg(&pdev->dev, "mode debugfs file is"
2434 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302435
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002436 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2437 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
2438
Amit Blay58b31472011-11-18 09:39:39 +02002439 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
2440 if (motg->pdata->otg_control == OTG_PMIC_CONTROL &&
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002441 motg->pdata->pmic_id_irq)
Amit Blay58b31472011-11-18 09:39:39 +02002442 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002443 ALLOW_PHY_RETENTION |
2444 ALLOW_PHY_COMP_DISABLE;
2445
Amit Blay58b31472011-11-18 09:39:39 +02002446 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
2447 motg->caps = ALLOW_PHY_RETENTION;
2448 }
2449
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002450 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302451 pm_runtime_set_active(&pdev->dev);
2452 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302453
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302454 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002455
2456remove_otg:
2457 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302458free_irq:
2459 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002460destroy_wlock:
2461 wake_lock_destroy(&motg->wlock);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302462 clk_disable(motg->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002463 msm_hsusb_ldo_enable(motg, 0);
2464free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302465 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002466free_init_vddcx:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302467 msm_hsusb_init_vddcx(motg, 0);
Anji jonnala7da3f262011-12-02 17:22:14 -08002468devote_xo_handle:
2469 msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
2470free_xo_handle:
2471 msm_xo_put(motg->xo_handle);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302472free_regs:
2473 iounmap(motg->regs);
2474put_core_clk:
2475 if (motg->core_clk)
2476 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002477
2478 if (!IS_ERR(motg->system_clk)) {
2479 clk_disable(motg->system_clk);
2480 clk_put(motg->system_clk);
2481 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302482put_pclk_src:
2483 if (!IS_ERR(motg->pclk_src)) {
2484 clk_disable(motg->pclk_src);
2485 clk_put(motg->pclk_src);
2486 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302487put_clk:
2488 clk_put(motg->clk);
2489put_phy_reset_clk:
Amit Blay02eff132011-09-21 16:46:24 +03002490 if (!IS_ERR(motg->phy_reset_clk))
2491 clk_put(motg->phy_reset_clk);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302492free_motg:
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05302493 if (motg->pdata->swfi_latency)
2494 pm_qos_remove_request(&motg->pm_qos_req_dma);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302495 kfree(motg);
2496 return ret;
2497}
2498
2499static int __devexit msm_otg_remove(struct platform_device *pdev)
2500{
2501 struct msm_otg *motg = platform_get_drvdata(pdev);
2502 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302503 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302504
2505 if (otg->host || otg->gadget)
2506 return -EBUSY;
2507
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302508 if (pdev->dev.of_node)
2509 msm_otg_setup_devices(pdev, motg->pdata->mode, false);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002510 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2511 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302512 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302513 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302514 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302515
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302516 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302517
2518 device_init_wakeup(&pdev->dev, 0);
2519 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002520 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302521
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302522 msm_hsusb_mhl_switch_enable(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002523 if (motg->pdata->pmic_id_irq)
2524 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302525 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302526 free_irq(motg->irq, motg);
2527
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302528 /*
2529 * Put PHY in low power mode.
2530 */
2531 ulpi_read(otg, 0x14);
2532 ulpi_write(otg, 0x08, 0x09);
2533
2534 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
2535 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
2536 if (readl(USB_PORTSC) & PORTSC_PHCD)
2537 break;
2538 udelay(1);
2539 cnt++;
2540 }
2541 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
2542 dev_err(otg->dev, "Unable to suspend PHY\n");
2543
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302544 clk_disable(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302545 if (motg->core_clk)
2546 clk_disable(motg->core_clk);
Amit Blay137575f2011-11-06 15:20:54 +02002547 if (!IS_ERR(motg->system_clk))
2548 clk_disable(motg->system_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302549 if (!IS_ERR(motg->pclk_src)) {
2550 clk_disable(motg->pclk_src);
2551 clk_put(motg->pclk_src);
2552 }
Anji jonnala7da3f262011-12-02 17:22:14 -08002553 msm_xo_put(motg->xo_handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002554 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302555 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002556 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302557
2558 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302559 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302560
Amit Blay02eff132011-09-21 16:46:24 +03002561 if (!IS_ERR(motg->phy_reset_clk))
2562 clk_put(motg->phy_reset_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302563 clk_put(motg->pclk);
2564 clk_put(motg->clk);
2565 if (motg->core_clk)
2566 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002567 if (!IS_ERR(motg->system_clk))
2568 clk_put(motg->system_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302569
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05302570 if (motg->pdata->swfi_latency)
2571 pm_qos_remove_request(&motg->pm_qos_req_dma);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302572
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05302573 kfree(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302574 return 0;
2575}
2576
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302577#ifdef CONFIG_PM_RUNTIME
2578static int msm_otg_runtime_idle(struct device *dev)
2579{
2580 struct msm_otg *motg = dev_get_drvdata(dev);
2581 struct otg_transceiver *otg = &motg->otg;
2582
2583 dev_dbg(dev, "OTG runtime idle\n");
2584
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302585 if (otg->state == OTG_STATE_UNDEFINED)
2586 return -EAGAIN;
2587 else
2588 return 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302589}
2590
2591static int msm_otg_runtime_suspend(struct device *dev)
2592{
2593 struct msm_otg *motg = dev_get_drvdata(dev);
2594
2595 dev_dbg(dev, "OTG runtime suspend\n");
2596 return msm_otg_suspend(motg);
2597}
2598
2599static int msm_otg_runtime_resume(struct device *dev)
2600{
2601 struct msm_otg *motg = dev_get_drvdata(dev);
2602
2603 dev_dbg(dev, "OTG runtime resume\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302604 pm_runtime_get_noresume(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302605 return msm_otg_resume(motg);
2606}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302607#endif
2608
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302609#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302610static int msm_otg_pm_suspend(struct device *dev)
2611{
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302612 int ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302613
2614 dev_dbg(dev, "OTG PM suspend\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302615
2616#ifdef CONFIG_PM_RUNTIME
2617 ret = pm_runtime_suspend(dev);
2618 if (ret > 0)
2619 ret = 0;
2620#else
2621 ret = msm_otg_suspend(dev_get_drvdata(dev));
2622#endif
2623 return ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302624}
2625
2626static int msm_otg_pm_resume(struct device *dev)
2627{
2628 struct msm_otg *motg = dev_get_drvdata(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302629
2630 dev_dbg(dev, "OTG PM resume\n");
2631
Manu Gautamf284c052011-09-08 16:52:48 +05302632#ifdef CONFIG_PM_RUNTIME
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302633 /*
Manu Gautamf284c052011-09-08 16:52:48 +05302634 * Do not resume hardware as part of system resume,
2635 * rather, wait for the ASYNC INT from the h/w
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302636 */
Gregory Beanebd8ca22011-10-11 12:02:35 -07002637 return 0;
Manu Gautamf284c052011-09-08 16:52:48 +05302638#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302639
Manu Gautamf284c052011-09-08 16:52:48 +05302640 return msm_otg_resume(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302641}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302642#endif
2643
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302644#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302645static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302646 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
2647 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
2648 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302649};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302650#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302651
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302652static struct of_device_id msm_otg_dt_match[] = {
2653 { .compatible = "qcom,hsusb-otg",
2654 },
2655 {}
2656};
2657
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302658static struct platform_driver msm_otg_driver = {
2659 .remove = __devexit_p(msm_otg_remove),
2660 .driver = {
2661 .name = DRIVER_NAME,
2662 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302663#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302664 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302665#endif
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302666 .of_match_table = msm_otg_dt_match,
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302667 },
2668};
2669
2670static int __init msm_otg_init(void)
2671{
2672 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
2673}
2674
2675static void __exit msm_otg_exit(void)
2676{
2677 platform_driver_unregister(&msm_otg_driver);
2678}
2679
2680module_init(msm_otg_init);
2681module_exit(msm_otg_exit);
2682
2683MODULE_LICENSE("GPL v2");
2684MODULE_DESCRIPTION("MSM USB transceiver driver");