blob: 550bdb06ae407d099de6f68720c417121ebbae2f [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;
Pavankumar Kondeti8a379b42011-12-12 13:07:23 +05301656 if (!test_bit(B_SESS_VLD, &motg->inputs) &&
1657 test_bit(ID, &motg->inputs)) {
1658 pm_runtime_put_noidle(otg->dev);
1659 pm_runtime_suspend(otg->dev);
1660 break;
1661 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301662 /* FALL THROUGH */
1663 case OTG_STATE_B_IDLE:
1664 dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001665 if ((!test_bit(ID, &motg->inputs) ||
1666 test_bit(ID_A, &motg->inputs)) && otg->host) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001667 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
1668 msm_otg_notify_charger(motg,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301669 IDEV_ACA_CHG_MAX);
1670 else if (test_bit(ID_A, &motg->inputs))
1671 msm_otg_notify_charger(motg,
1672 IDEV_ACA_CHG_MAX - IUNIT);
1673 else if (motg->pdata->vbus_power)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001674 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301675 msm_otg_start_host(otg, 1);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301676 /*
1677 * Link can not generate PHY_ALT interrupt
1678 * in host mode when no device is attached
1679 * to the port. It is also observed PHY_ALT
1680 * interrupt missing upon Micro-A cable disconnect.
1681 * Hence disable PHY_ALT interrupt and perform
1682 * polling to detect RID change.
1683 */
1684 msm_chg_enable_aca_det(motg);
1685 msm_chg_disable_aca_intr(motg);
1686 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301687 otg->state = OTG_STATE_A_HOST;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301688 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1689 switch (motg->chg_state) {
1690 case USB_CHG_STATE_UNDEFINED:
1691 msm_chg_detect_work(&motg->chg_work.work);
1692 break;
1693 case USB_CHG_STATE_DETECTED:
1694 switch (motg->chg_type) {
1695 case USB_DCP_CHARGER:
1696 msm_otg_notify_charger(motg,
1697 IDEV_CHG_MAX);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301698 pm_runtime_put_noidle(otg->dev);
1699 pm_runtime_suspend(otg->dev);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301700 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301701 case USB_ACA_B_CHARGER:
1702 msm_otg_notify_charger(motg,
1703 IDEV_ACA_CHG_MAX);
1704 /*
1705 * (ID_B --> ID_C) PHY_ALT interrupt can
1706 * not be detected in LPM.
1707 */
1708 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301709 case USB_CDP_CHARGER:
1710 msm_otg_notify_charger(motg,
1711 IDEV_CHG_MAX);
1712 msm_otg_start_peripheral(otg, 1);
1713 otg->state = OTG_STATE_B_PERIPHERAL;
1714 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301715 case USB_ACA_C_CHARGER:
1716 msm_otg_notify_charger(motg,
1717 IDEV_ACA_CHG_MAX);
1718 msm_otg_start_peripheral(otg, 1);
1719 otg->state = OTG_STATE_B_PERIPHERAL;
1720 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301721 case USB_SDP_CHARGER:
1722 msm_otg_notify_charger(motg, IUNIT);
1723 msm_otg_start_peripheral(otg, 1);
1724 otg->state = OTG_STATE_B_PERIPHERAL;
1725 break;
1726 default:
1727 break;
1728 }
1729 break;
1730 default:
1731 break;
1732 }
1733 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301734 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301735 msm_otg_notify_charger(motg, 0);
1736 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1737 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301738 msm_otg_reset(otg);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301739 pm_runtime_put_noidle(otg->dev);
1740 pm_runtime_suspend(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301741 }
1742 break;
1743 case OTG_STATE_B_PERIPHERAL:
1744 dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
1745 if (!test_bit(B_SESS_VLD, &motg->inputs) ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001746 !test_bit(ID, &motg->inputs) ||
1747 !test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301748 msm_otg_start_peripheral(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001749 otg->state = OTG_STATE_B_IDLE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001750 schedule_work(w);
1751 } else if (test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301752 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001753 }
1754 break;
1755 case OTG_STATE_A_HOST:
1756 dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
1757 if (test_bit(ID, &motg->inputs) &&
1758 !test_bit(ID_A, &motg->inputs)) {
1759 msm_otg_start_host(otg, 0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301760 if (motg->pdata->vbus_power) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001761 motg->pdata->vbus_power(0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301762 msleep(100); /* TA_WAIT_VFALL */
1763 }
1764 /*
1765 * Exit point of host mode.
1766 *
1767 * 1. Micro-A cable disconnect: Just schedule
1768 * the work. PHY is reset in B_IDLE and LPM
1769 * is allowed.
1770 * 2. ID_GND --> ID_B: No need to reset the PHY.
1771 * HCD core clears all PORTSC bits and initializes
1772 * the controller to host mode in remove_hcd.
1773 * Restore PORTSC transceiver select bits (ULPI)
1774 * and reset the controller to change MODE bits.
1775 * PHY_ALT interrupt can not occur in host mode.
1776 */
1777 del_timer_sync(&motg->id_timer);
1778 if (motg->chg_state != USB_CHG_STATE_UNDEFINED) {
1779 msm_otg_link_reset(motg);
1780 msm_chg_enable_aca_intr(motg);
1781 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301782 otg->state = OTG_STATE_B_IDLE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301783 schedule_work(w);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001784 } else if (test_bit(ID_A, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785 if (motg->pdata->vbus_power)
1786 motg->pdata->vbus_power(0);
1787 msm_otg_notify_charger(motg,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301788 IDEV_ACA_CHG_MAX - motg->mA_port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001789 } else if (!test_bit(ID, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001790 msm_otg_notify_charger(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001791 if (motg->pdata->vbus_power)
1792 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301793 }
1794 break;
1795 default:
1796 break;
1797 }
1798}
1799
1800static irqreturn_t msm_otg_irq(int irq, void *data)
1801{
1802 struct msm_otg *motg = data;
1803 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001804 u32 otgsc = 0, usbsts;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301805
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301806 if (atomic_read(&motg->in_lpm)) {
1807 disable_irq_nosync(irq);
1808 motg->async_int = 1;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301809 pm_request_resume(otg->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301810 return IRQ_HANDLED;
1811 }
1812
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001813 usbsts = readl(USB_USBSTS);
1814 if ((usbsts & PHY_ALT_INT)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301815 dev_dbg(otg->dev, "PHY_ALT interrupt\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001816 writel(PHY_ALT_INT, USB_USBSTS);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301817 if (msm_chg_check_aca_intr(motg)) {
1818 dev_dbg(otg->dev, "ACA work from IRQ\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001819 schedule_work(&motg->sm_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301820 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001821 return IRQ_HANDLED;
1822 }
1823
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301824 otgsc = readl(USB_OTGSC);
1825 if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1826 return IRQ_NONE;
1827
1828 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301829 if (otgsc & OTGSC_ID) {
1830 dev_dbg(otg->dev, "ID set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301831 set_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301832 } else {
1833 dev_dbg(otg->dev, "ID clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301834 clear_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301835 msm_chg_enable_aca_det(motg);
1836 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001837 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301838 } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301839 if (otgsc & OTGSC_BSV) {
1840 dev_dbg(otg->dev, "BSV set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301841 set_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301842 } else {
1843 dev_dbg(otg->dev, "BSV clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301844 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301845 msm_chg_check_aca_intr(motg);
1846 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001847 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301848 }
1849
1850 writel(otgsc, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001851 return IRQ_HANDLED;
1852}
1853
1854static void msm_otg_set_vbus_state(int online)
1855{
1856 struct msm_otg *motg = the_msm_otg;
1857
1858 /* We depend on PMIC for only VBUS ON interrupt */
Chiranjeevi Velempati62206042011-12-09 23:10:40 +05301859 if (!atomic_read(&motg->in_lpm) || !online || motg->async_int)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001860 return;
1861
1862 /*
1863 * Let interrupt handler take care of resuming
1864 * the hardware.
1865 */
1866 msm_otg_irq(motg->irq, (void *) motg);
1867}
1868
1869static irqreturn_t msm_pmic_id_irq(int irq, void *data)
1870{
1871 struct msm_otg *motg = data;
1872
1873 if (atomic_read(&motg->in_lpm) && !motg->async_int)
1874 msm_otg_irq(motg->irq, motg);
1875
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301876 return IRQ_HANDLED;
1877}
1878
1879static int msm_otg_mode_show(struct seq_file *s, void *unused)
1880{
1881 struct msm_otg *motg = s->private;
1882 struct otg_transceiver *otg = &motg->otg;
1883
1884 switch (otg->state) {
1885 case OTG_STATE_A_HOST:
1886 seq_printf(s, "host\n");
1887 break;
1888 case OTG_STATE_B_PERIPHERAL:
1889 seq_printf(s, "peripheral\n");
1890 break;
1891 default:
1892 seq_printf(s, "none\n");
1893 break;
1894 }
1895
1896 return 0;
1897}
1898
1899static int msm_otg_mode_open(struct inode *inode, struct file *file)
1900{
1901 return single_open(file, msm_otg_mode_show, inode->i_private);
1902}
1903
1904static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1905 size_t count, loff_t *ppos)
1906{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05301907 struct seq_file *s = file->private_data;
1908 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301909 char buf[16];
1910 struct otg_transceiver *otg = &motg->otg;
1911 int status = count;
1912 enum usb_mode_type req_mode;
1913
1914 memset(buf, 0x00, sizeof(buf));
1915
1916 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1917 status = -EFAULT;
1918 goto out;
1919 }
1920
1921 if (!strncmp(buf, "host", 4)) {
1922 req_mode = USB_HOST;
1923 } else if (!strncmp(buf, "peripheral", 10)) {
1924 req_mode = USB_PERIPHERAL;
1925 } else if (!strncmp(buf, "none", 4)) {
1926 req_mode = USB_NONE;
1927 } else {
1928 status = -EINVAL;
1929 goto out;
1930 }
1931
1932 switch (req_mode) {
1933 case USB_NONE:
1934 switch (otg->state) {
1935 case OTG_STATE_A_HOST:
1936 case OTG_STATE_B_PERIPHERAL:
1937 set_bit(ID, &motg->inputs);
1938 clear_bit(B_SESS_VLD, &motg->inputs);
1939 break;
1940 default:
1941 goto out;
1942 }
1943 break;
1944 case USB_PERIPHERAL:
1945 switch (otg->state) {
1946 case OTG_STATE_B_IDLE:
1947 case OTG_STATE_A_HOST:
1948 set_bit(ID, &motg->inputs);
1949 set_bit(B_SESS_VLD, &motg->inputs);
1950 break;
1951 default:
1952 goto out;
1953 }
1954 break;
1955 case USB_HOST:
1956 switch (otg->state) {
1957 case OTG_STATE_B_IDLE:
1958 case OTG_STATE_B_PERIPHERAL:
1959 clear_bit(ID, &motg->inputs);
1960 break;
1961 default:
1962 goto out;
1963 }
1964 break;
1965 default:
1966 goto out;
1967 }
1968
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301969 pm_runtime_resume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301970 schedule_work(&motg->sm_work);
1971out:
1972 return status;
1973}
1974
1975const struct file_operations msm_otg_mode_fops = {
1976 .open = msm_otg_mode_open,
1977 .read = seq_read,
1978 .write = msm_otg_mode_write,
1979 .llseek = seq_lseek,
1980 .release = single_release,
1981};
1982
Anji jonnalad270e2d2011-08-09 11:28:32 +05301983static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
1984{
1985 struct msm_otg *motg = s->private;
1986
1987 seq_printf(s, chg_to_string(motg->chg_type));
1988 return 0;
1989}
1990
1991static int msm_otg_chg_open(struct inode *inode, struct file *file)
1992{
1993 return single_open(file, msm_otg_show_chg_type, inode->i_private);
1994}
1995
1996const struct file_operations msm_otg_chg_fops = {
1997 .open = msm_otg_chg_open,
1998 .read = seq_read,
1999 .llseek = seq_lseek,
2000 .release = single_release,
2001};
2002
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302003static int msm_otg_aca_show(struct seq_file *s, void *unused)
2004{
2005 if (debug_aca_enabled)
2006 seq_printf(s, "enabled\n");
2007 else
2008 seq_printf(s, "disabled\n");
2009
2010 return 0;
2011}
2012
2013static int msm_otg_aca_open(struct inode *inode, struct file *file)
2014{
2015 return single_open(file, msm_otg_aca_show, inode->i_private);
2016}
2017
2018static ssize_t msm_otg_aca_write(struct file *file, const char __user *ubuf,
2019 size_t count, loff_t *ppos)
2020{
2021 char buf[8];
2022
2023 memset(buf, 0x00, sizeof(buf));
2024
2025 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
2026 return -EFAULT;
2027
2028 if (!strncmp(buf, "enable", 6))
2029 debug_aca_enabled = true;
2030 else
2031 debug_aca_enabled = false;
2032
2033 return count;
2034}
2035
2036const struct file_operations msm_otg_aca_fops = {
2037 .open = msm_otg_aca_open,
2038 .read = seq_read,
2039 .write = msm_otg_aca_write,
2040 .llseek = seq_lseek,
2041 .release = single_release,
2042};
2043
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302044static struct dentry *msm_otg_dbg_root;
2045static struct dentry *msm_otg_dbg_mode;
Anji jonnalad270e2d2011-08-09 11:28:32 +05302046static struct dentry *msm_otg_chg_type;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302047static struct dentry *msm_otg_dbg_aca;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302048
2049static int msm_otg_debugfs_init(struct msm_otg *motg)
2050{
Anji jonnalad270e2d2011-08-09 11:28:32 +05302051
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302052 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
2053
2054 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
2055 return -ENODEV;
2056
Anji jonnalad270e2d2011-08-09 11:28:32 +05302057 if (motg->pdata->mode == USB_OTG &&
2058 motg->pdata->otg_control == OTG_USER_CONTROL) {
2059
2060 msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
2061 S_IWUSR, msm_otg_dbg_root, motg,
2062 &msm_otg_mode_fops);
2063
2064 if (!msm_otg_dbg_mode) {
2065 debugfs_remove(msm_otg_dbg_root);
2066 msm_otg_dbg_root = NULL;
2067 return -ENODEV;
2068 }
2069 }
2070
2071 msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
2072 msm_otg_dbg_root, motg,
2073 &msm_otg_chg_fops);
2074
2075 if (!msm_otg_chg_type) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302076 debugfs_remove_recursive(msm_otg_dbg_root);
2077 return -ENODEV;
2078 }
2079
2080 msm_otg_dbg_aca = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
2081 msm_otg_dbg_root, motg,
2082 &msm_otg_aca_fops);
2083
2084 if (!msm_otg_dbg_aca) {
2085 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302086 return -ENODEV;
2087 }
2088
2089 return 0;
2090}
2091
2092static void msm_otg_debugfs_cleanup(void)
2093{
Anji jonnalad270e2d2011-08-09 11:28:32 +05302094 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302095}
2096
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302097static u64 msm_otg_dma_mask = DMA_BIT_MASK(64);
2098static struct platform_device *msm_otg_add_pdev(
2099 struct platform_device *ofdev, const char *name)
2100{
2101 struct platform_device *pdev;
2102 const struct resource *res = ofdev->resource;
2103 unsigned int num = ofdev->num_resources;
2104 int retval;
2105
2106 pdev = platform_device_alloc(name, -1);
2107 if (!pdev) {
2108 retval = -ENOMEM;
2109 goto error;
2110 }
2111
2112 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
2113 pdev->dev.dma_mask = &msm_otg_dma_mask;
2114
2115 if (num) {
2116 retval = platform_device_add_resources(pdev, res, num);
2117 if (retval)
2118 goto error;
2119 }
2120
2121 retval = platform_device_add(pdev);
2122 if (retval)
2123 goto error;
2124
2125 return pdev;
2126
2127error:
2128 platform_device_put(pdev);
2129 return ERR_PTR(retval);
2130}
2131
2132static int msm_otg_setup_devices(struct platform_device *ofdev,
2133 enum usb_mode_type mode, bool init)
2134{
2135 const char *gadget_name = "msm_hsusb";
2136 const char *host_name = "msm_hsusb_host";
2137 static struct platform_device *gadget_pdev;
2138 static struct platform_device *host_pdev;
2139 int retval = 0;
2140
2141 if (!init) {
2142 if (gadget_pdev)
2143 platform_device_unregister(gadget_pdev);
2144 if (host_pdev)
2145 platform_device_unregister(host_pdev);
2146 return 0;
2147 }
2148
2149 switch (mode) {
2150 case USB_OTG:
2151 /* fall through */
2152 case USB_PERIPHERAL:
2153 gadget_pdev = msm_otg_add_pdev(ofdev, gadget_name);
2154 if (IS_ERR(gadget_pdev)) {
2155 retval = PTR_ERR(gadget_pdev);
2156 break;
2157 }
2158 if (mode == USB_PERIPHERAL)
2159 break;
2160 /* fall through */
2161 case USB_HOST:
2162 host_pdev = msm_otg_add_pdev(ofdev, host_name);
2163 if (IS_ERR(host_pdev)) {
2164 retval = PTR_ERR(host_pdev);
2165 if (mode == USB_OTG)
2166 platform_device_unregister(gadget_pdev);
2167 }
2168 break;
2169 default:
2170 break;
2171 }
2172
2173 return retval;
2174}
2175
2176struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
2177{
2178 struct device_node *node = pdev->dev.of_node;
2179 struct msm_otg_platform_data *pdata;
2180 int len = 0;
2181
2182 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
2183 if (!pdata) {
2184 pr_err("unable to allocate platform data\n");
2185 return NULL;
2186 }
2187 of_get_property(node, "qcom,hsusb-otg-phy-init-seq", &len);
2188 if (len) {
2189 pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
2190 if (!pdata->phy_init_seq)
2191 return NULL;
2192 of_property_read_u32_array(node, "qcom,hsusb-otg-phy-init-seq",
2193 pdata->phy_init_seq,
2194 len/sizeof(*pdata->phy_init_seq));
2195 }
2196 of_property_read_u32(node, "qcom,hsusb-otg-power-budget",
2197 &pdata->power_budget);
2198 of_property_read_u32(node, "qcom,hsusb-otg-mode",
2199 &pdata->mode);
2200 of_property_read_u32(node, "qcom,hsusb-otg-otg-control",
2201 &pdata->otg_control);
2202 of_property_read_u32(node, "qcom,hsusb-otg-default-mode",
2203 &pdata->default_mode);
2204 of_property_read_u32(node, "qcom,hsusb-otg-phy-type",
2205 &pdata->phy_type);
2206 of_property_read_u32(node, "qcom,hsusb-otg-pmic-id-irq",
2207 &pdata->pmic_id_irq);
2208 of_property_read_string(node, "qcom,hsusb-otg-pclk-src-name",
2209 &pdata->pclk_src_name);
2210 return pdata;
2211}
2212
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302213static int __init msm_otg_probe(struct platform_device *pdev)
2214{
2215 int ret = 0;
2216 struct resource *res;
2217 struct msm_otg *motg;
2218 struct otg_transceiver *otg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302219 struct msm_otg_platform_data *pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302220
2221 dev_info(&pdev->dev, "msm_otg probe\n");
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302222
2223 if (pdev->dev.of_node) {
2224 dev_dbg(&pdev->dev, "device tree enabled\n");
2225 pdata = msm_otg_dt_to_pdata(pdev);
2226 if (!pdata)
2227 return -ENOMEM;
2228 ret = msm_otg_setup_devices(pdev, pdata->mode, true);
2229 if (ret) {
2230 dev_err(&pdev->dev, "devices setup failed\n");
2231 return ret;
2232 }
2233 } else if (!pdev->dev.platform_data) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302234 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
2235 return -ENODEV;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302236 } else {
2237 pdata = pdev->dev.platform_data;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302238 }
2239
2240 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
2241 if (!motg) {
2242 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
2243 return -ENOMEM;
2244 }
2245
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002246 the_msm_otg = motg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302247 motg->pdata = pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302248 otg = &motg->otg;
2249 otg->dev = &pdev->dev;
2250
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302251 /*
2252 * ACA ID_GND threshold range is overlapped with OTG ID_FLOAT. Hence
2253 * PHY treat ACA ID_GND as float and no interrupt is generated. But
2254 * PMIC can detect ACA ID_GND and generate an interrupt.
2255 */
2256 if (aca_enabled() && motg->pdata->otg_control != OTG_PMIC_CONTROL) {
2257 dev_err(&pdev->dev, "ACA can not be enabled without PMIC\n");
2258 ret = -EINVAL;
2259 goto free_motg;
2260 }
2261
Amit Blay02eff132011-09-21 16:46:24 +03002262 /* Some targets don't support PHY clock. */
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302263 motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
Amit Blay02eff132011-09-21 16:46:24 +03002264 if (IS_ERR(motg->phy_reset_clk))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302265 dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302266
2267 motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
2268 if (IS_ERR(motg->clk)) {
2269 dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
2270 ret = PTR_ERR(motg->clk);
2271 goto put_phy_reset_clk;
2272 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302273 clk_set_rate(motg->clk, 60000000);
2274
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05302275 /* pm qos request to prevent apps idle power collapse */
2276 if (motg->pdata->swfi_latency)
2277 pm_qos_add_request(&motg->pm_qos_req_dma,
2278 PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302279 /*
2280 * If USB Core is running its protocol engine based on CORE CLK,
2281 * CORE CLK must be running at >55Mhz for correct HSUSB
2282 * operation and USB core cannot tolerate frequency changes on
2283 * CORE CLK. For such USB cores, vote for maximum clk frequency
2284 * on pclk source
2285 */
2286 if (motg->pdata->pclk_src_name) {
2287 motg->pclk_src = clk_get(&pdev->dev,
2288 motg->pdata->pclk_src_name);
2289 if (IS_ERR(motg->pclk_src))
2290 goto put_clk;
2291 clk_set_rate(motg->pclk_src, INT_MAX);
2292 clk_enable(motg->pclk_src);
2293 } else
2294 motg->pclk_src = ERR_PTR(-ENOENT);
2295
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302296 motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
2297 if (IS_ERR(motg->pclk)) {
2298 dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
2299 ret = PTR_ERR(motg->pclk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302300 goto put_pclk_src;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302301 }
2302
Amit Blay02eff132011-09-21 16:46:24 +03002303 motg->system_clk = clk_get(&pdev->dev, "usb_hs_system_clk");
2304 if (!IS_ERR(motg->system_clk))
2305 clk_enable(motg->system_clk);
2306
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302307 /*
2308 * USB core clock is not present on all MSM chips. This
2309 * clock is introduced to remove the dependency on AXI
2310 * bus frequency.
2311 */
2312 motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
2313 if (IS_ERR(motg->core_clk))
2314 motg->core_clk = NULL;
2315
2316 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2317 if (!res) {
2318 dev_err(&pdev->dev, "failed to get platform resource mem\n");
2319 ret = -ENODEV;
2320 goto put_core_clk;
2321 }
2322
2323 motg->regs = ioremap(res->start, resource_size(res));
2324 if (!motg->regs) {
2325 dev_err(&pdev->dev, "ioremap failed\n");
2326 ret = -ENOMEM;
2327 goto put_core_clk;
2328 }
2329 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
2330
2331 motg->irq = platform_get_irq(pdev, 0);
2332 if (!motg->irq) {
2333 dev_err(&pdev->dev, "platform_get_irq failed\n");
2334 ret = -ENODEV;
2335 goto free_regs;
2336 }
2337
Anji jonnala7da3f262011-12-02 17:22:14 -08002338 motg->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, "usb");
2339 if (IS_ERR(motg->xo_handle)) {
2340 dev_err(&pdev->dev, "%s not able to get the handle "
2341 "to vote for TCXO D0 buffer\n", __func__);
2342 ret = PTR_ERR(motg->xo_handle);
2343 goto free_regs;
2344 }
2345
2346 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
2347 if (ret) {
2348 dev_err(&pdev->dev, "%s failed to vote for TCXO "
2349 "D0 buffer%d\n", __func__, ret);
2350 goto free_xo_handle;
2351 }
2352
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302353 clk_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302354
2355 ret = msm_hsusb_init_vddcx(motg, 1);
2356 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002357 dev_err(&pdev->dev, "hsusb vddcx init failed\n");
Anji jonnala7da3f262011-12-02 17:22:14 -08002358 goto devote_xo_handle;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302359 }
2360
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002361 ret = msm_hsusb_config_vddcx(1);
2362 if (ret) {
2363 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
2364 goto free_init_vddcx;
2365 }
2366
Anji jonnala11aa5c42011-05-04 10:19:48 +05302367 ret = msm_hsusb_ldo_init(motg, 1);
2368 if (ret) {
2369 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002370 goto free_init_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302371 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002372
2373 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302374 if (ret) {
2375 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002376 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302377 }
2378
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302379 if (motg->core_clk)
2380 clk_enable(motg->core_clk);
2381
2382 writel(0, USB_USBINTR);
2383 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002384 /* Ensure that above STOREs are completed before enabling interrupts */
2385 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302386
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002387 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302388 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302389 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302390 setup_timer(&motg->id_timer, msm_otg_id_timer_func,
2391 (unsigned long) motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302392 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
2393 "msm_otg", motg);
2394 if (ret) {
2395 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002396 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302397 }
2398
2399 otg->init = msm_otg_reset;
2400 otg->set_host = msm_otg_set_host;
2401 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302402 otg->set_power = msm_otg_set_power;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302403 otg->set_suspend = msm_otg_set_suspend;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302404
2405 otg->io_ops = &msm_otg_io_ops;
2406
2407 ret = otg_set_transceiver(&motg->otg);
2408 if (ret) {
2409 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
2410 goto free_irq;
2411 }
2412
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002413 if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
2414 if (motg->pdata->pmic_id_irq) {
2415 ret = request_irq(motg->pdata->pmic_id_irq,
2416 msm_pmic_id_irq,
2417 IRQF_TRIGGER_RISING |
2418 IRQF_TRIGGER_FALLING,
2419 "msm_otg", motg);
2420 if (ret) {
2421 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
2422 goto remove_otg;
2423 }
2424 } else {
2425 ret = -ENODEV;
2426 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
2427 goto remove_otg;
2428 }
2429 }
2430
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302431 msm_hsusb_mhl_switch_enable(motg, 1);
2432
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302433 platform_set_drvdata(pdev, motg);
2434 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002435 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302436
Anji jonnalad270e2d2011-08-09 11:28:32 +05302437 ret = msm_otg_debugfs_init(motg);
2438 if (ret)
2439 dev_dbg(&pdev->dev, "mode debugfs file is"
2440 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302441
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002442 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2443 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
2444
Amit Blay58b31472011-11-18 09:39:39 +02002445 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
2446 if (motg->pdata->otg_control == OTG_PMIC_CONTROL &&
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002447 motg->pdata->pmic_id_irq)
Amit Blay58b31472011-11-18 09:39:39 +02002448 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002449 ALLOW_PHY_RETENTION |
2450 ALLOW_PHY_COMP_DISABLE;
2451
Amit Blay58b31472011-11-18 09:39:39 +02002452 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
2453 motg->caps = ALLOW_PHY_RETENTION;
2454 }
2455
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002456 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302457 pm_runtime_set_active(&pdev->dev);
2458 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302459
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302460 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002461
2462remove_otg:
2463 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302464free_irq:
2465 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002466destroy_wlock:
2467 wake_lock_destroy(&motg->wlock);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302468 clk_disable(motg->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002469 msm_hsusb_ldo_enable(motg, 0);
2470free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302471 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002472free_init_vddcx:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302473 msm_hsusb_init_vddcx(motg, 0);
Anji jonnala7da3f262011-12-02 17:22:14 -08002474devote_xo_handle:
2475 msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
2476free_xo_handle:
2477 msm_xo_put(motg->xo_handle);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302478free_regs:
2479 iounmap(motg->regs);
2480put_core_clk:
2481 if (motg->core_clk)
2482 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002483
2484 if (!IS_ERR(motg->system_clk)) {
2485 clk_disable(motg->system_clk);
2486 clk_put(motg->system_clk);
2487 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302488put_pclk_src:
2489 if (!IS_ERR(motg->pclk_src)) {
2490 clk_disable(motg->pclk_src);
2491 clk_put(motg->pclk_src);
2492 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302493put_clk:
2494 clk_put(motg->clk);
2495put_phy_reset_clk:
Amit Blay02eff132011-09-21 16:46:24 +03002496 if (!IS_ERR(motg->phy_reset_clk))
2497 clk_put(motg->phy_reset_clk);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302498free_motg:
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05302499 if (motg->pdata->swfi_latency)
2500 pm_qos_remove_request(&motg->pm_qos_req_dma);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302501 kfree(motg);
2502 return ret;
2503}
2504
2505static int __devexit msm_otg_remove(struct platform_device *pdev)
2506{
2507 struct msm_otg *motg = platform_get_drvdata(pdev);
2508 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302509 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302510
2511 if (otg->host || otg->gadget)
2512 return -EBUSY;
2513
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302514 if (pdev->dev.of_node)
2515 msm_otg_setup_devices(pdev, motg->pdata->mode, false);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002516 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2517 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302518 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302519 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302520 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302521
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302522 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302523
2524 device_init_wakeup(&pdev->dev, 0);
2525 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002526 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302527
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302528 msm_hsusb_mhl_switch_enable(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002529 if (motg->pdata->pmic_id_irq)
2530 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302531 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302532 free_irq(motg->irq, motg);
2533
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302534 /*
2535 * Put PHY in low power mode.
2536 */
2537 ulpi_read(otg, 0x14);
2538 ulpi_write(otg, 0x08, 0x09);
2539
2540 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
2541 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
2542 if (readl(USB_PORTSC) & PORTSC_PHCD)
2543 break;
2544 udelay(1);
2545 cnt++;
2546 }
2547 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
2548 dev_err(otg->dev, "Unable to suspend PHY\n");
2549
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302550 clk_disable(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302551 if (motg->core_clk)
2552 clk_disable(motg->core_clk);
Amit Blay137575f2011-11-06 15:20:54 +02002553 if (!IS_ERR(motg->system_clk))
2554 clk_disable(motg->system_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302555 if (!IS_ERR(motg->pclk_src)) {
2556 clk_disable(motg->pclk_src);
2557 clk_put(motg->pclk_src);
2558 }
Anji jonnala7da3f262011-12-02 17:22:14 -08002559 msm_xo_put(motg->xo_handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002560 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302561 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002562 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302563
2564 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302565 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302566
Amit Blay02eff132011-09-21 16:46:24 +03002567 if (!IS_ERR(motg->phy_reset_clk))
2568 clk_put(motg->phy_reset_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302569 clk_put(motg->pclk);
2570 clk_put(motg->clk);
2571 if (motg->core_clk)
2572 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002573 if (!IS_ERR(motg->system_clk))
2574 clk_put(motg->system_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302575
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05302576 if (motg->pdata->swfi_latency)
2577 pm_qos_remove_request(&motg->pm_qos_req_dma);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302578
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05302579 kfree(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302580 return 0;
2581}
2582
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302583#ifdef CONFIG_PM_RUNTIME
2584static int msm_otg_runtime_idle(struct device *dev)
2585{
2586 struct msm_otg *motg = dev_get_drvdata(dev);
2587 struct otg_transceiver *otg = &motg->otg;
2588
2589 dev_dbg(dev, "OTG runtime idle\n");
2590
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302591 if (otg->state == OTG_STATE_UNDEFINED)
2592 return -EAGAIN;
2593 else
2594 return 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302595}
2596
2597static int msm_otg_runtime_suspend(struct device *dev)
2598{
2599 struct msm_otg *motg = dev_get_drvdata(dev);
2600
2601 dev_dbg(dev, "OTG runtime suspend\n");
2602 return msm_otg_suspend(motg);
2603}
2604
2605static int msm_otg_runtime_resume(struct device *dev)
2606{
2607 struct msm_otg *motg = dev_get_drvdata(dev);
2608
2609 dev_dbg(dev, "OTG runtime resume\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302610 pm_runtime_get_noresume(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302611 return msm_otg_resume(motg);
2612}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302613#endif
2614
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302615#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302616static int msm_otg_pm_suspend(struct device *dev)
2617{
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302618 int ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302619
2620 dev_dbg(dev, "OTG PM suspend\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302621
2622#ifdef CONFIG_PM_RUNTIME
2623 ret = pm_runtime_suspend(dev);
2624 if (ret > 0)
2625 ret = 0;
2626#else
2627 ret = msm_otg_suspend(dev_get_drvdata(dev));
2628#endif
2629 return ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302630}
2631
2632static int msm_otg_pm_resume(struct device *dev)
2633{
2634 struct msm_otg *motg = dev_get_drvdata(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302635
2636 dev_dbg(dev, "OTG PM resume\n");
2637
Manu Gautamf284c052011-09-08 16:52:48 +05302638#ifdef CONFIG_PM_RUNTIME
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302639 /*
Manu Gautamf284c052011-09-08 16:52:48 +05302640 * Do not resume hardware as part of system resume,
2641 * rather, wait for the ASYNC INT from the h/w
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302642 */
Gregory Beanebd8ca22011-10-11 12:02:35 -07002643 return 0;
Manu Gautamf284c052011-09-08 16:52:48 +05302644#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302645
Manu Gautamf284c052011-09-08 16:52:48 +05302646 return msm_otg_resume(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302647}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302648#endif
2649
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302650#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302651static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302652 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
2653 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
2654 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302655};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302656#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302657
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302658static struct of_device_id msm_otg_dt_match[] = {
2659 { .compatible = "qcom,hsusb-otg",
2660 },
2661 {}
2662};
2663
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302664static struct platform_driver msm_otg_driver = {
2665 .remove = __devexit_p(msm_otg_remove),
2666 .driver = {
2667 .name = DRIVER_NAME,
2668 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302669#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302670 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302671#endif
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302672 .of_match_table = msm_otg_dt_match,
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302673 },
2674};
2675
2676static int __init msm_otg_init(void)
2677{
2678 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
2679}
2680
2681static void __exit msm_otg_exit(void)
2682{
2683 platform_driver_unregister(&msm_otg_driver);
2684}
2685
2686module_init(msm_otg_init);
2687module_exit(msm_otg_exit);
2688
2689MODULE_LICENSE("GPL v2");
2690MODULE_DESCRIPTION("MSM USB transceiver driver");