blob: ec922f13b343ec0454b07ba819335b6b15bec8d6 [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>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053040
41#include <mach/clk.h>
Anji jonnala7da3f262011-12-02 17:22:14 -080042#include <mach/msm_xo.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053043
44#define MSM_USB_BASE (motg->regs)
45#define DRIVER_NAME "msm_otg"
46
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053047#define ID_TIMER_FREQ (jiffies + msecs_to_jiffies(2000))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053048#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
Anji jonnala11aa5c42011-05-04 10:19:48 +053049
50#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
51#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
52#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
53#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
54
55#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
56#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
57#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
58#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
59
Vamsi Krishna132b2762011-11-11 16:09:20 -080060#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
Anji jonnala11aa5c42011-05-04 10:19:48 +053061#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
62
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070063static struct msm_otg *the_msm_otg;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053064static bool debug_aca_enabled;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070065
Anji jonnala11aa5c42011-05-04 10:19:48 +053066static struct regulator *hsusb_3p3;
67static struct regulator *hsusb_1p8;
68static struct regulator *hsusb_vddcx;
69
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053070static inline bool aca_enabled(void)
71{
72#ifdef CONFIG_USB_MSM_ACA
73 return true;
74#else
75 return debug_aca_enabled;
76#endif
77}
78
Anji jonnala11aa5c42011-05-04 10:19:48 +053079static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
80{
81 int ret = 0;
82
83 if (init) {
84 hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
85 if (IS_ERR(hsusb_vddcx)) {
86 dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
87 return PTR_ERR(hsusb_vddcx);
88 }
89
90 ret = regulator_set_voltage(hsusb_vddcx,
91 USB_PHY_VDD_DIG_VOL_MIN,
92 USB_PHY_VDD_DIG_VOL_MAX);
93 if (ret) {
94 dev_err(motg->otg.dev, "unable to set the voltage "
95 "for hsusb vddcx\n");
96 regulator_put(hsusb_vddcx);
97 return ret;
98 }
99
100 ret = regulator_enable(hsusb_vddcx);
101 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700102 regulator_set_voltage(hsusb_vddcx, 0,
103 USB_PHY_VDD_DIG_VOL_MIN);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530104 regulator_put(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700105 dev_err(motg->otg.dev, "unable to enable the hsusb vddcx\n");
106 return ret;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530107 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700108
Anji jonnala11aa5c42011-05-04 10:19:48 +0530109 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700110
Anji jonnala11aa5c42011-05-04 10:19:48 +0530111 ret = regulator_disable(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700112 if (ret) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530113 dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700114 return ret;
115 }
116
117 ret = regulator_set_voltage(hsusb_vddcx, 0,
118 USB_PHY_VDD_DIG_VOL_MIN);
119 if (ret) {
120 dev_err(motg->otg.dev, "unable to set the voltage"
121 "for hsusb vddcx\n");
122 return ret;
123 }
Anji jonnala11aa5c42011-05-04 10:19:48 +0530124
125 regulator_put(hsusb_vddcx);
126 }
127
128 return ret;
129}
130
131static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
132{
133 int rc = 0;
134
135 if (init) {
136 hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
137 if (IS_ERR(hsusb_3p3)) {
138 dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
139 return PTR_ERR(hsusb_3p3);
140 }
141
142 rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
143 USB_PHY_3P3_VOL_MAX);
144 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700145 dev_err(motg->otg.dev, "unable to set voltage level for"
146 "hsusb 3p3\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530147 goto put_3p3;
148 }
149 hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
150 if (IS_ERR(hsusb_1p8)) {
151 dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
152 rc = PTR_ERR(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153 goto put_3p3_lpm;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530154 }
155 rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
156 USB_PHY_1P8_VOL_MAX);
157 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700158 dev_err(motg->otg.dev, "unable to set voltage level for"
159 "hsusb 1p8\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530160 goto put_1p8;
161 }
162
163 return 0;
164 }
165
Anji jonnala11aa5c42011-05-04 10:19:48 +0530166put_1p8:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700167 regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530168 regulator_put(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700169put_3p3_lpm:
170 regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530171put_3p3:
172 regulator_put(hsusb_3p3);
173 return rc;
174}
175
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530176#ifdef CONFIG_PM_SLEEP
177#define USB_PHY_SUSP_DIG_VOL 500000
178static int msm_hsusb_config_vddcx(int high)
179{
180 int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
181 int min_vol;
182 int ret;
183
184 if (high)
185 min_vol = USB_PHY_VDD_DIG_VOL_MIN;
186 else
187 min_vol = USB_PHY_SUSP_DIG_VOL;
188
189 ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
190 if (ret) {
191 pr_err("%s: unable to set the voltage for regulator "
192 "HSUSB_VDDCX\n", __func__);
193 return ret;
194 }
195
196 pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
197
198 return ret;
199}
Hemant Kumar8e7bd072011-08-01 14:14:24 -0700200#else
201static int msm_hsusb_config_vddcx(int high)
202{
203 return 0;
204}
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530205#endif
206
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
Anji jonnala11aa5c42011-05-04 10:19:48 +0530208{
209 int ret = 0;
210
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530211 if (IS_ERR(hsusb_1p8)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530212 pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
213 return -ENODEV;
214 }
215
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530216 if (IS_ERR(hsusb_3p3)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530217 pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
218 return -ENODEV;
219 }
220
221 if (on) {
222 ret = regulator_set_optimum_mode(hsusb_1p8,
223 USB_PHY_1P8_HPM_LOAD);
224 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700225 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530226 "HSUSB_1p8\n", __func__);
227 return ret;
228 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700229
230 ret = regulator_enable(hsusb_1p8);
231 if (ret) {
232 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 1p8\n",
233 __func__);
234 regulator_set_optimum_mode(hsusb_1p8, 0);
235 return ret;
236 }
237
Anji jonnala11aa5c42011-05-04 10:19:48 +0530238 ret = regulator_set_optimum_mode(hsusb_3p3,
239 USB_PHY_3P3_HPM_LOAD);
240 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700241 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530242 "HSUSB_3p3\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700243 regulator_set_optimum_mode(hsusb_1p8, 0);
244 regulator_disable(hsusb_1p8);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530245 return ret;
246 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700247
248 ret = regulator_enable(hsusb_3p3);
249 if (ret) {
250 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 3p3\n",
251 __func__);
252 regulator_set_optimum_mode(hsusb_3p3, 0);
253 regulator_set_optimum_mode(hsusb_1p8, 0);
254 regulator_disable(hsusb_1p8);
255 return ret;
256 }
257
Anji jonnala11aa5c42011-05-04 10:19:48 +0530258 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700259 ret = regulator_disable(hsusb_1p8);
260 if (ret) {
261 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 1p8\n",
262 __func__);
263 return ret;
264 }
265
266 ret = regulator_set_optimum_mode(hsusb_1p8, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530267 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700268 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530269 "HSUSB_1p8\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270
271 ret = regulator_disable(hsusb_3p3);
272 if (ret) {
273 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 3p3\n",
274 __func__);
275 return ret;
276 }
277 ret = regulator_set_optimum_mode(hsusb_3p3, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530278 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700279 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530280 "HSUSB_3p3\n", __func__);
281 }
282
283 pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
284 return ret < 0 ? ret : 0;
285}
286
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530287static void msm_hsusb_mhl_switch_enable(struct msm_otg *motg, bool on)
288{
289 static struct regulator *mhl_analog_switch;
290 struct msm_otg_platform_data *pdata = motg->pdata;
291
292 if (!pdata->mhl_enable)
293 return;
294
295 if (on) {
296 mhl_analog_switch = regulator_get(motg->otg.dev,
297 "mhl_ext_3p3v");
298 if (IS_ERR(mhl_analog_switch)) {
299 pr_err("Unable to get mhl_analog_switch\n");
300 return;
301 }
302
303 if (regulator_enable(mhl_analog_switch)) {
304 pr_err("unable to enable mhl_analog_switch\n");
305 goto put_analog_switch;
306 }
307 return;
308 }
309
310 regulator_disable(mhl_analog_switch);
311put_analog_switch:
312 regulator_put(mhl_analog_switch);
313}
314
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530315static int ulpi_read(struct otg_transceiver *otg, u32 reg)
316{
317 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
318 int cnt = 0;
319
320 /* initiate read operation */
321 writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
322 USB_ULPI_VIEWPORT);
323
324 /* wait for completion */
325 while (cnt < ULPI_IO_TIMEOUT_USEC) {
326 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
327 break;
328 udelay(1);
329 cnt++;
330 }
331
332 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
333 dev_err(otg->dev, "ulpi_read: timeout %08x\n",
334 readl(USB_ULPI_VIEWPORT));
335 return -ETIMEDOUT;
336 }
337 return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
338}
339
340static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
341{
342 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
343 int cnt = 0;
344
345 /* initiate write operation */
346 writel(ULPI_RUN | ULPI_WRITE |
347 ULPI_ADDR(reg) | ULPI_DATA(val),
348 USB_ULPI_VIEWPORT);
349
350 /* wait for completion */
351 while (cnt < ULPI_IO_TIMEOUT_USEC) {
352 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
353 break;
354 udelay(1);
355 cnt++;
356 }
357
358 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
359 dev_err(otg->dev, "ulpi_write: timeout\n");
360 return -ETIMEDOUT;
361 }
362 return 0;
363}
364
365static struct otg_io_access_ops msm_otg_io_ops = {
366 .read = ulpi_read,
367 .write = ulpi_write,
368};
369
370static void ulpi_init(struct msm_otg *motg)
371{
372 struct msm_otg_platform_data *pdata = motg->pdata;
373 int *seq = pdata->phy_init_seq;
374
375 if (!seq)
376 return;
377
378 while (seq[0] >= 0) {
379 dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
380 seq[0], seq[1]);
381 ulpi_write(&motg->otg, seq[0], seq[1]);
382 seq += 2;
383 }
384}
385
386static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
387{
388 int ret;
389
390 if (assert) {
391 ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
392 if (ret)
393 dev_err(motg->otg.dev, "usb hs_clk assert failed\n");
394 } else {
395 ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
396 if (ret)
397 dev_err(motg->otg.dev, "usb hs_clk deassert failed\n");
398 }
399 return ret;
400}
401
402static int msm_otg_phy_clk_reset(struct msm_otg *motg)
403{
404 int ret;
405
Amit Blay02eff132011-09-21 16:46:24 +0300406 if (IS_ERR(motg->phy_reset_clk))
407 return 0;
408
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530409 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
410 if (ret) {
411 dev_err(motg->otg.dev, "usb phy clk assert failed\n");
412 return ret;
413 }
414 usleep_range(10000, 12000);
415 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
416 if (ret)
417 dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
418 return ret;
419}
420
421static int msm_otg_phy_reset(struct msm_otg *motg)
422{
423 u32 val;
424 int ret;
425 int retries;
426
427 ret = msm_otg_link_clk_reset(motg, 1);
428 if (ret)
429 return ret;
430 ret = msm_otg_phy_clk_reset(motg);
431 if (ret)
432 return ret;
433 ret = msm_otg_link_clk_reset(motg, 0);
434 if (ret)
435 return ret;
436
437 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
438 writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
439
440 for (retries = 3; retries > 0; retries--) {
441 ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
442 ULPI_CLR(ULPI_FUNC_CTRL));
443 if (!ret)
444 break;
445 ret = msm_otg_phy_clk_reset(motg);
446 if (ret)
447 return ret;
448 }
449 if (!retries)
450 return -ETIMEDOUT;
451
452 /* This reset calibrates the phy, if the above write succeeded */
453 ret = msm_otg_phy_clk_reset(motg);
454 if (ret)
455 return ret;
456
457 for (retries = 3; retries > 0; retries--) {
458 ret = ulpi_read(&motg->otg, ULPI_DEBUG);
459 if (ret != -ETIMEDOUT)
460 break;
461 ret = msm_otg_phy_clk_reset(motg);
462 if (ret)
463 return ret;
464 }
465 if (!retries)
466 return -ETIMEDOUT;
467
468 dev_info(motg->otg.dev, "phy_reset: success\n");
469 return 0;
470}
471
472#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530473static int msm_otg_link_reset(struct msm_otg *motg)
474{
475 int cnt = 0;
476
477 writel_relaxed(USBCMD_RESET, USB_USBCMD);
478 while (cnt < LINK_RESET_TIMEOUT_USEC) {
479 if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
480 break;
481 udelay(1);
482 cnt++;
483 }
484 if (cnt >= LINK_RESET_TIMEOUT_USEC)
485 return -ETIMEDOUT;
486
487 /* select ULPI phy */
488 writel_relaxed(0x80000000, USB_PORTSC);
489 writel_relaxed(0x0, USB_AHBBURST);
490 writel_relaxed(0x00, USB_AHBMODE);
491
492 return 0;
493}
494
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530495static int msm_otg_reset(struct otg_transceiver *otg)
496{
497 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
498 struct msm_otg_platform_data *pdata = motg->pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530499 int ret;
500 u32 val = 0;
501 u32 ulpi_val = 0;
502
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700503 clk_enable(motg->clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530504 ret = msm_otg_phy_reset(motg);
505 if (ret) {
506 dev_err(otg->dev, "phy_reset failed\n");
507 return ret;
508 }
509
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530510 ret = msm_otg_link_reset(motg);
511 if (ret) {
512 dev_err(otg->dev, "link reset failed\n");
513 return ret;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530514 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530515 msleep(100);
Anji jonnalaa8b8d732011-12-06 10:03:24 +0530516
517 ulpi_init(motg);
518
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700519 /* Ensure that RESET operation is completed before turning off clock */
520 mb();
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530521
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700522 clk_disable(motg->clk);
523
524 val = readl_relaxed(USB_OTGSC);
525 if (pdata->mode == USB_OTG) {
526 ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
527 val |= OTGSC_IDIE | OTGSC_BSVIE;
528 } else if (pdata->mode == USB_PERIPHERAL) {
529 ulpi_val = ULPI_INT_SESS_VALID;
530 val |= OTGSC_BSVIE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530531 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700532 writel_relaxed(val, USB_OTGSC);
533 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
534 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
535
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530536 return 0;
537}
538
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530539static int msm_otg_set_suspend(struct otg_transceiver *otg, int suspend)
540{
541 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
542
543 /*
544 * Allow bus suspend only for host mode. Device mode bus suspend
545 * is not implemented yet.
546 */
547 if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530548 /*
549 * ID_GND --> ID_A transition can not be detected in LPM.
550 * Disallow host bus suspend when ACA is enabled.
551 */
552 if (suspend && !aca_enabled())
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530553 pm_runtime_put(otg->dev);
554 else
555 pm_runtime_resume(otg->dev);
556 }
557
558 return 0;
559}
560
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530561#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530562#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
563
564#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530565static int msm_otg_suspend(struct msm_otg *motg)
566{
567 struct otg_transceiver *otg = &motg->otg;
568 struct usb_bus *bus = otg->host;
569 struct msm_otg_platform_data *pdata = motg->pdata;
570 int cnt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700571 bool session_active;
Amit Blay58b31472011-11-18 09:39:39 +0200572 u32 phy_ctrl_val = 0;
Anji jonnala7da3f262011-12-02 17:22:14 -0800573 unsigned ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530574
575 if (atomic_read(&motg->in_lpm))
576 return 0;
577
578 disable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700579 session_active = (otg->host && !test_bit(ID, &motg->inputs)) ||
580 test_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530581 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530582 * Chipidea 45-nm PHY suspend sequence:
583 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530584 * Interrupt Latch Register auto-clear feature is not present
585 * in all PHY versions. Latch register is clear on read type.
586 * Clear latch register to avoid spurious wakeup from
587 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530588 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530589 * PHY comparators are disabled when PHY enters into low power
590 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
591 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
592 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530593 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530594 * PLL is not turned off when PHY enters into low power mode (LPM).
595 * Disable PLL for maximum power savings.
596 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530597
598 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
599 ulpi_read(otg, 0x14);
600 if (pdata->otg_control == OTG_PHY_CONTROL)
601 ulpi_write(otg, 0x01, 0x30);
602 ulpi_write(otg, 0x08, 0x09);
603 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530604
605 /*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700606 * Turn off the OTG comparators, if depends on PMIC for
607 * VBUS and ID notifications.
608 */
609 if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !session_active) {
610 ulpi_write(otg, OTG_COMP_DISABLE,
611 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
612 motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
613 }
614
615 /*
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530616 * PHY may take some time or even fail to enter into low power
617 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
618 * in failure case.
619 */
620 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
621 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
622 if (readl(USB_PORTSC) & PORTSC_PHCD)
623 break;
624 udelay(1);
625 cnt++;
626 }
627
628 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
629 dev_err(otg->dev, "Unable to suspend PHY\n");
630 msm_otg_reset(otg);
631 enable_irq(motg->irq);
632 return -ETIMEDOUT;
633 }
634
635 /*
636 * PHY has capability to generate interrupt asynchronously in low
637 * power mode (LPM). This interrupt is level triggered. So USB IRQ
638 * line must be disabled till async interrupt enable bit is cleared
639 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
640 * block data communication from PHY.
641 */
642 writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
643
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700644 if (motg->caps & ALLOW_PHY_RETENTION && !session_active) {
Amit Blay58b31472011-11-18 09:39:39 +0200645 phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
646 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
647 /* Enable PHY HV interrupts to wake MPM/Link */
648 phy_ctrl_val |=
649 (PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
650
651 writel_relaxed(phy_ctrl_val & ~PHY_RETEN, USB_PHY_CTRL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700652 motg->lpm_flags |= PHY_RETENTIONED;
653 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530654
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700655 /* Ensure that above operation is completed before turning off clocks */
656 mb();
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530657 clk_disable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530658 if (motg->core_clk)
659 clk_disable(motg->core_clk);
660
Amit Blay137575f2011-11-06 15:20:54 +0200661 if (!IS_ERR(motg->system_clk))
662 clk_disable(motg->system_clk);
663
Anji jonnala0f73cac2011-05-04 10:19:46 +0530664 if (!IS_ERR(motg->pclk_src))
665 clk_disable(motg->pclk_src);
666
Anji jonnala7da3f262011-12-02 17:22:14 -0800667 /* usb phy no more require TCXO clock, hence vote for TCXO disable */
668 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
669 if (ret)
670 dev_err(otg->dev, "%s failed to devote for "
671 "TCXO D0 buffer%d\n", __func__, ret);
672
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700673 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !session_active) {
674 msm_hsusb_ldo_enable(motg, 0);
675 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530676 }
677
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530678 if (motg->lpm_flags & PHY_RETENTIONED) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700679 msm_hsusb_config_vddcx(0);
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530680 msm_hsusb_mhl_switch_enable(motg, 0);
681 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700682
683 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530684 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700685 if (motg->pdata->pmic_id_irq)
686 enable_irq_wake(motg->pdata->pmic_id_irq);
687 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530688 if (bus)
689 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
690
691 atomic_set(&motg->in_lpm, 1);
692 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530694
695 dev_info(otg->dev, "USB in low power mode\n");
696
697 return 0;
698}
699
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530700static int msm_otg_resume(struct msm_otg *motg)
701{
702 struct otg_transceiver *otg = &motg->otg;
703 struct usb_bus *bus = otg->host;
704 int cnt = 0;
705 unsigned temp;
Amit Blay58b31472011-11-18 09:39:39 +0200706 u32 phy_ctrl_val = 0;
Anji jonnala7da3f262011-12-02 17:22:14 -0800707 unsigned ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530708
709 if (!atomic_read(&motg->in_lpm))
710 return 0;
711
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700712 wake_lock(&motg->wlock);
Anji jonnala7da3f262011-12-02 17:22:14 -0800713
714 /* Vote for TCXO when waking up the phy */
715 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
716 if (ret)
717 dev_err(otg->dev, "%s failed to vote for "
718 "TCXO D0 buffer%d\n", __func__, ret);
719
Anji jonnala0f73cac2011-05-04 10:19:46 +0530720 if (!IS_ERR(motg->pclk_src))
721 clk_enable(motg->pclk_src);
722
Amit Blay137575f2011-11-06 15:20:54 +0200723 if (!IS_ERR(motg->system_clk))
724 clk_enable(motg->system_clk);
725
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530726 clk_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530727 if (motg->core_clk)
728 clk_enable(motg->core_clk);
729
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700730 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
731 msm_hsusb_ldo_enable(motg, 1);
732 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
733 }
734
735 if (motg->lpm_flags & PHY_RETENTIONED) {
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530736 msm_hsusb_mhl_switch_enable(motg, 1);
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530737 msm_hsusb_config_vddcx(1);
Amit Blay58b31472011-11-18 09:39:39 +0200738 phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
739 phy_ctrl_val |= PHY_RETEN;
740 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
741 /* Disable PHY HV interrupts */
742 phy_ctrl_val &=
743 ~(PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
744 writel_relaxed(phy_ctrl_val, USB_PHY_CTRL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700745 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530746 }
747
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530748 temp = readl(USB_USBCMD);
749 temp &= ~ASYNC_INTR_CTRL;
750 temp &= ~ULPI_STP_CTRL;
751 writel(temp, USB_USBCMD);
752
753 /*
754 * PHY comes out of low power mode (LPM) in case of wakeup
755 * from asynchronous interrupt.
756 */
757 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
758 goto skip_phy_resume;
759
760 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
761 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
762 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
763 break;
764 udelay(1);
765 cnt++;
766 }
767
768 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
769 /*
770 * This is a fatal error. Reset the link and
771 * PHY. USB state can not be restored. Re-insertion
772 * of USB cable is the only way to get USB working.
773 */
774 dev_err(otg->dev, "Unable to resume USB."
775 "Re-plugin the cable\n");
776 msm_otg_reset(otg);
777 }
778
779skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700780 /* Turn on the OTG comparators on resume */
781 if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
782 ulpi_write(otg, OTG_COMP_DISABLE,
783 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
784 motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
785 }
786 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530787 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700788 if (motg->pdata->pmic_id_irq)
789 disable_irq_wake(motg->pdata->pmic_id_irq);
790 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530791 if (bus)
792 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
793
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530794 atomic_set(&motg->in_lpm, 0);
795
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530796 if (aca_enabled() && !irq_read_line(motg->pdata->pmic_id_irq)) {
797 clear_bit(ID, &motg->inputs);
798 schedule_work(&motg->sm_work);
799 }
800
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530801 if (motg->async_int) {
802 motg->async_int = 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530803 enable_irq(motg->irq);
804 }
805
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530806 dev_info(otg->dev, "USB exited from low power mode\n");
807
808 return 0;
809}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530810#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530811
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530812static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
813{
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530814 if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
815 motg->chg_type == USB_ACA_A_CHARGER ||
816 motg->chg_type == USB_ACA_B_CHARGER ||
817 motg->chg_type == USB_ACA_C_CHARGER) &&
818 mA > IDEV_ACA_CHG_LIMIT)
819 mA = IDEV_ACA_CHG_LIMIT;
820
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530821 if (motg->cur_power == mA)
822 return;
823
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530824 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700825 pm8921_charger_vbus_draw(mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530826 motg->cur_power = mA;
827}
828
829static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
830{
831 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
832
833 /*
834 * Gadget driver uses set_power method to notify about the
835 * available current based on suspend/configured states.
836 *
837 * IDEV_CHG can be drawn irrespective of suspend/un-configured
838 * states when CDP/ACA is connected.
839 */
840 if (motg->chg_type == USB_SDP_CHARGER)
841 msm_otg_notify_charger(motg, mA);
842
843 return 0;
844}
845
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530846static void msm_otg_start_host(struct otg_transceiver *otg, int on)
847{
848 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
849 struct msm_otg_platform_data *pdata = motg->pdata;
850 struct usb_hcd *hcd;
851
852 if (!otg->host)
853 return;
854
855 hcd = bus_to_hcd(otg->host);
856
857 if (on) {
858 dev_dbg(otg->dev, "host on\n");
859
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530860 /*
861 * Some boards have a switch cotrolled by gpio
862 * to enable/disable internal HUB. Enable internal
863 * HUB before kicking the host.
864 */
865 if (pdata->setup_gpio)
866 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530867 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530868 } else {
869 dev_dbg(otg->dev, "host off\n");
870
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530871 usb_remove_hcd(hcd);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530872 /* HCD core reset all bits of PORTSC. select ULPI phy */
873 writel_relaxed(0x80000000, USB_PORTSC);
874
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530875 if (pdata->setup_gpio)
876 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530877 }
878}
879
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700880static int msm_otg_usbdev_notify(struct notifier_block *self,
881 unsigned long action, void *priv)
882{
883 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530884 struct usb_device *udev = priv;
885
886 if (!aca_enabled())
887 goto out;
888
889 if (action == USB_BUS_ADD || action == USB_BUS_REMOVE)
890 goto out;
891
892 if (udev->bus != motg->otg.host)
893 goto out;
894 /*
895 * Interested in devices connected directly to the root hub.
896 * ACA dock can supply IDEV_CHG irrespective devices connected
897 * on the accessory port.
898 */
899 if (!udev->parent || udev->parent->parent ||
900 motg->chg_type == USB_ACA_DOCK_CHARGER)
901 goto out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700902
903 switch (action) {
904 case USB_DEVICE_ADD:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530905 usb_disable_autosuspend(udev);
906 /* fall through */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700907 case USB_DEVICE_CONFIG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700908 if (udev->actconfig)
909 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
910 else
911 motg->mA_port = IUNIT;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530912 break;
913 case USB_DEVICE_REMOVE:
914 motg->mA_port = IUNIT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915 break;
916 default:
917 break;
918 }
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530919 if (test_bit(ID_A, &motg->inputs))
920 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX -
921 motg->mA_port);
922out:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700923 return NOTIFY_OK;
924}
925
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530926static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
927{
928 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
929 struct usb_hcd *hcd;
930
931 /*
932 * Fail host registration if this board can support
933 * only peripheral configuration.
934 */
935 if (motg->pdata->mode == USB_PERIPHERAL) {
936 dev_info(otg->dev, "Host mode is not supported\n");
937 return -ENODEV;
938 }
939
940 if (!host) {
941 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530942 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700943 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530944 msm_otg_start_host(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700945 if (motg->pdata->vbus_power)
946 motg->pdata->vbus_power(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530947 otg->host = NULL;
948 otg->state = OTG_STATE_UNDEFINED;
949 schedule_work(&motg->sm_work);
950 } else {
951 otg->host = NULL;
952 }
953
954 return 0;
955 }
956
957 hcd = bus_to_hcd(host);
958 hcd->power_budget = motg->pdata->power_budget;
959
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700960 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
961 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530962 otg->host = host;
963 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
964
965 /*
966 * Kick the state machine work, if peripheral is not supported
967 * or peripheral is already registered with us.
968 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530969 if (motg->pdata->mode == USB_HOST || otg->gadget) {
970 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530971 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530972 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530973
974 return 0;
975}
976
977static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
978{
979 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
980 struct msm_otg_platform_data *pdata = motg->pdata;
981
982 if (!otg->gadget)
983 return;
984
985 if (on) {
986 dev_dbg(otg->dev, "gadget on\n");
987 /*
988 * Some boards have a switch cotrolled by gpio
989 * to enable/disable internal HUB. Disable internal
990 * HUB before kicking the gadget.
991 */
992 if (pdata->setup_gpio)
993 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
994 usb_gadget_vbus_connect(otg->gadget);
995 } else {
996 dev_dbg(otg->dev, "gadget off\n");
997 usb_gadget_vbus_disconnect(otg->gadget);
998 if (pdata->setup_gpio)
999 pdata->setup_gpio(OTG_STATE_UNDEFINED);
1000 }
1001
1002}
1003
1004static int msm_otg_set_peripheral(struct otg_transceiver *otg,
1005 struct usb_gadget *gadget)
1006{
1007 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1008
1009 /*
1010 * Fail peripheral registration if this board can support
1011 * only host configuration.
1012 */
1013 if (motg->pdata->mode == USB_HOST) {
1014 dev_info(otg->dev, "Peripheral mode is not supported\n");
1015 return -ENODEV;
1016 }
1017
1018 if (!gadget) {
1019 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301020 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301021 msm_otg_start_peripheral(otg, 0);
1022 otg->gadget = NULL;
1023 otg->state = OTG_STATE_UNDEFINED;
1024 schedule_work(&motg->sm_work);
1025 } else {
1026 otg->gadget = NULL;
1027 }
1028
1029 return 0;
1030 }
1031 otg->gadget = gadget;
1032 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
1033
1034 /*
1035 * Kick the state machine work, if host is not supported
1036 * or host is already registered with us.
1037 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301038 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
1039 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301040 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301041 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301042
1043 return 0;
1044}
1045
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001046static bool msm_chg_aca_detect(struct msm_otg *motg)
1047{
1048 struct otg_transceiver *otg = &motg->otg;
1049 u32 int_sts;
1050 bool ret = false;
1051
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301052 if (!aca_enabled())
1053 goto out;
1054
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001055 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
1056 goto out;
1057
1058 int_sts = ulpi_read(otg, 0x87);
1059 switch (int_sts & 0x1C) {
1060 case 0x08:
1061 if (!test_and_set_bit(ID_A, &motg->inputs)) {
1062 dev_dbg(otg->dev, "ID_A\n");
1063 motg->chg_type = USB_ACA_A_CHARGER;
1064 motg->chg_state = USB_CHG_STATE_DETECTED;
1065 clear_bit(ID_B, &motg->inputs);
1066 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301067 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001068 ret = true;
1069 }
1070 break;
1071 case 0x0C:
1072 if (!test_and_set_bit(ID_B, &motg->inputs)) {
1073 dev_dbg(otg->dev, "ID_B\n");
1074 motg->chg_type = USB_ACA_B_CHARGER;
1075 motg->chg_state = USB_CHG_STATE_DETECTED;
1076 clear_bit(ID_A, &motg->inputs);
1077 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301078 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001079 ret = true;
1080 }
1081 break;
1082 case 0x10:
1083 if (!test_and_set_bit(ID_C, &motg->inputs)) {
1084 dev_dbg(otg->dev, "ID_C\n");
1085 motg->chg_type = USB_ACA_C_CHARGER;
1086 motg->chg_state = USB_CHG_STATE_DETECTED;
1087 clear_bit(ID_A, &motg->inputs);
1088 clear_bit(ID_B, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301089 set_bit(ID, &motg->inputs);
1090 ret = true;
1091 }
1092 break;
1093 case 0x04:
1094 if (test_and_clear_bit(ID, &motg->inputs)) {
1095 dev_dbg(otg->dev, "ID_GND\n");
1096 motg->chg_type = USB_INVALID_CHARGER;
1097 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1098 clear_bit(ID_A, &motg->inputs);
1099 clear_bit(ID_B, &motg->inputs);
1100 clear_bit(ID_C, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001101 ret = true;
1102 }
1103 break;
1104 default:
1105 ret = test_and_clear_bit(ID_A, &motg->inputs) |
1106 test_and_clear_bit(ID_B, &motg->inputs) |
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301107 test_and_clear_bit(ID_C, &motg->inputs) |
1108 !test_and_set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001109 if (ret) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301110 dev_dbg(otg->dev, "ID A/B/C/GND is no more\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001111 motg->chg_type = USB_INVALID_CHARGER;
1112 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1113 }
1114 }
1115out:
1116 return ret;
1117}
1118
1119static void msm_chg_enable_aca_det(struct msm_otg *motg)
1120{
1121 struct otg_transceiver *otg = &motg->otg;
1122
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301123 if (!aca_enabled())
1124 return;
1125
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001126 switch (motg->pdata->phy_type) {
1127 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301128 /* Disable ID_GND in link and PHY */
1129 writel_relaxed(readl_relaxed(USB_OTGSC) & ~(OTGSC_IDPU |
1130 OTGSC_IDIE), USB_OTGSC);
1131 ulpi_write(otg, 0x01, 0x0C);
1132 ulpi_write(otg, 0x10, 0x0F);
1133 ulpi_write(otg, 0x10, 0x12);
1134 /* Enable ACA ID detection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001135 ulpi_write(otg, 0x20, 0x85);
1136 break;
1137 default:
1138 break;
1139 }
1140}
1141
1142static void msm_chg_enable_aca_intr(struct msm_otg *motg)
1143{
1144 struct otg_transceiver *otg = &motg->otg;
1145
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301146 if (!aca_enabled())
1147 return;
1148
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001149 switch (motg->pdata->phy_type) {
1150 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301151 /* Enable ACA Detection interrupt (on any RID change) */
1152 ulpi_write(otg, 0x01, 0x94);
1153 break;
1154 default:
1155 break;
1156 }
1157}
1158
1159static void msm_chg_disable_aca_intr(struct msm_otg *motg)
1160{
1161 struct otg_transceiver *otg = &motg->otg;
1162
1163 if (!aca_enabled())
1164 return;
1165
1166 switch (motg->pdata->phy_type) {
1167 case SNPS_28NM_INTEGRATED_PHY:
1168 ulpi_write(otg, 0x01, 0x95);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001169 break;
1170 default:
1171 break;
1172 }
1173}
1174
1175static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1176{
1177 struct otg_transceiver *otg = &motg->otg;
1178 bool ret = false;
1179
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301180 if (!aca_enabled())
1181 return ret;
1182
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001183 switch (motg->pdata->phy_type) {
1184 case SNPS_28NM_INTEGRATED_PHY:
1185 if (ulpi_read(otg, 0x91) & 1) {
1186 dev_dbg(otg->dev, "RID change\n");
1187 ulpi_write(otg, 0x01, 0x92);
1188 ret = msm_chg_aca_detect(motg);
1189 }
1190 default:
1191 break;
1192 }
1193 return ret;
1194}
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301195
1196static void msm_otg_id_timer_func(unsigned long data)
1197{
1198 struct msm_otg *motg = (struct msm_otg *) data;
1199
1200 if (!aca_enabled())
1201 return;
1202
1203 if (atomic_read(&motg->in_lpm)) {
1204 dev_dbg(motg->otg.dev, "timer: in lpm\n");
1205 return;
1206 }
1207
1208 if (msm_chg_check_aca_intr(motg)) {
1209 dev_dbg(motg->otg.dev, "timer: aca work\n");
1210 schedule_work(&motg->sm_work);
1211 }
1212
1213 if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs))
1214 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
1215}
1216
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301217static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1218{
1219 struct otg_transceiver *otg = &motg->otg;
1220 u32 chg_det;
1221 bool ret = false;
1222
1223 switch (motg->pdata->phy_type) {
1224 case CI_45NM_INTEGRATED_PHY:
1225 chg_det = ulpi_read(otg, 0x34);
1226 ret = chg_det & (1 << 4);
1227 break;
1228 case SNPS_28NM_INTEGRATED_PHY:
1229 chg_det = ulpi_read(otg, 0x87);
1230 ret = chg_det & 1;
1231 break;
1232 default:
1233 break;
1234 }
1235 return ret;
1236}
1237
1238static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1239{
1240 struct otg_transceiver *otg = &motg->otg;
1241 u32 chg_det;
1242
1243 switch (motg->pdata->phy_type) {
1244 case CI_45NM_INTEGRATED_PHY:
1245 chg_det = ulpi_read(otg, 0x34);
1246 /* Turn off charger block */
1247 chg_det |= ~(1 << 1);
1248 ulpi_write(otg, chg_det, 0x34);
1249 udelay(20);
1250 /* control chg block via ULPI */
1251 chg_det &= ~(1 << 3);
1252 ulpi_write(otg, chg_det, 0x34);
1253 /* put it in host mode for enabling D- source */
1254 chg_det &= ~(1 << 2);
1255 ulpi_write(otg, chg_det, 0x34);
1256 /* Turn on chg detect block */
1257 chg_det &= ~(1 << 1);
1258 ulpi_write(otg, chg_det, 0x34);
1259 udelay(20);
1260 /* enable chg detection */
1261 chg_det &= ~(1 << 0);
1262 ulpi_write(otg, chg_det, 0x34);
1263 break;
1264 case SNPS_28NM_INTEGRATED_PHY:
1265 /*
1266 * Configure DM as current source, DP as current sink
1267 * and enable battery charging comparators.
1268 */
1269 ulpi_write(otg, 0x8, 0x85);
1270 ulpi_write(otg, 0x2, 0x85);
1271 ulpi_write(otg, 0x1, 0x85);
1272 break;
1273 default:
1274 break;
1275 }
1276}
1277
1278static bool msm_chg_check_primary_det(struct msm_otg *motg)
1279{
1280 struct otg_transceiver *otg = &motg->otg;
1281 u32 chg_det;
1282 bool ret = false;
1283
1284 switch (motg->pdata->phy_type) {
1285 case CI_45NM_INTEGRATED_PHY:
1286 chg_det = ulpi_read(otg, 0x34);
1287 ret = chg_det & (1 << 4);
1288 break;
1289 case SNPS_28NM_INTEGRATED_PHY:
1290 chg_det = ulpi_read(otg, 0x87);
1291 ret = chg_det & 1;
1292 break;
1293 default:
1294 break;
1295 }
1296 return ret;
1297}
1298
1299static void msm_chg_enable_primary_det(struct msm_otg *motg)
1300{
1301 struct otg_transceiver *otg = &motg->otg;
1302 u32 chg_det;
1303
1304 switch (motg->pdata->phy_type) {
1305 case CI_45NM_INTEGRATED_PHY:
1306 chg_det = ulpi_read(otg, 0x34);
1307 /* enable chg detection */
1308 chg_det &= ~(1 << 0);
1309 ulpi_write(otg, chg_det, 0x34);
1310 break;
1311 case SNPS_28NM_INTEGRATED_PHY:
1312 /*
1313 * Configure DP as current source, DM as current sink
1314 * and enable battery charging comparators.
1315 */
1316 ulpi_write(otg, 0x2, 0x85);
1317 ulpi_write(otg, 0x1, 0x85);
1318 break;
1319 default:
1320 break;
1321 }
1322}
1323
1324static bool msm_chg_check_dcd(struct msm_otg *motg)
1325{
1326 struct otg_transceiver *otg = &motg->otg;
1327 u32 line_state;
1328 bool ret = false;
1329
1330 switch (motg->pdata->phy_type) {
1331 case CI_45NM_INTEGRATED_PHY:
1332 line_state = ulpi_read(otg, 0x15);
1333 ret = !(line_state & 1);
1334 break;
1335 case SNPS_28NM_INTEGRATED_PHY:
1336 line_state = ulpi_read(otg, 0x87);
1337 ret = line_state & 2;
1338 break;
1339 default:
1340 break;
1341 }
1342 return ret;
1343}
1344
1345static void msm_chg_disable_dcd(struct msm_otg *motg)
1346{
1347 struct otg_transceiver *otg = &motg->otg;
1348 u32 chg_det;
1349
1350 switch (motg->pdata->phy_type) {
1351 case CI_45NM_INTEGRATED_PHY:
1352 chg_det = ulpi_read(otg, 0x34);
1353 chg_det &= ~(1 << 5);
1354 ulpi_write(otg, chg_det, 0x34);
1355 break;
1356 case SNPS_28NM_INTEGRATED_PHY:
1357 ulpi_write(otg, 0x10, 0x86);
1358 break;
1359 default:
1360 break;
1361 }
1362}
1363
1364static void msm_chg_enable_dcd(struct msm_otg *motg)
1365{
1366 struct otg_transceiver *otg = &motg->otg;
1367 u32 chg_det;
1368
1369 switch (motg->pdata->phy_type) {
1370 case CI_45NM_INTEGRATED_PHY:
1371 chg_det = ulpi_read(otg, 0x34);
1372 /* Turn on D+ current source */
1373 chg_det |= (1 << 5);
1374 ulpi_write(otg, chg_det, 0x34);
1375 break;
1376 case SNPS_28NM_INTEGRATED_PHY:
1377 /* Data contact detection enable */
1378 ulpi_write(otg, 0x10, 0x85);
1379 break;
1380 default:
1381 break;
1382 }
1383}
1384
1385static void msm_chg_block_on(struct msm_otg *motg)
1386{
1387 struct otg_transceiver *otg = &motg->otg;
1388 u32 func_ctrl, chg_det;
1389
1390 /* put the controller in non-driving mode */
1391 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1392 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1393 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1394 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1395
1396 switch (motg->pdata->phy_type) {
1397 case CI_45NM_INTEGRATED_PHY:
1398 chg_det = ulpi_read(otg, 0x34);
1399 /* control chg block via ULPI */
1400 chg_det &= ~(1 << 3);
1401 ulpi_write(otg, chg_det, 0x34);
1402 /* Turn on chg detect block */
1403 chg_det &= ~(1 << 1);
1404 ulpi_write(otg, chg_det, 0x34);
1405 udelay(20);
1406 break;
1407 case SNPS_28NM_INTEGRATED_PHY:
1408 /* Clear charger detecting control bits */
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301409 ulpi_write(otg, 0x1F, 0x86);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301410 /* Clear alt interrupt latch and enable bits */
1411 ulpi_write(otg, 0x1F, 0x92);
1412 ulpi_write(otg, 0x1F, 0x95);
1413 udelay(100);
1414 break;
1415 default:
1416 break;
1417 }
1418}
1419
1420static void msm_chg_block_off(struct msm_otg *motg)
1421{
1422 struct otg_transceiver *otg = &motg->otg;
1423 u32 func_ctrl, chg_det;
1424
1425 switch (motg->pdata->phy_type) {
1426 case CI_45NM_INTEGRATED_PHY:
1427 chg_det = ulpi_read(otg, 0x34);
1428 /* Turn off charger block */
1429 chg_det |= ~(1 << 1);
1430 ulpi_write(otg, chg_det, 0x34);
1431 break;
1432 case SNPS_28NM_INTEGRATED_PHY:
1433 /* Clear charger detecting control bits */
1434 ulpi_write(otg, 0x3F, 0x86);
1435 /* Clear alt interrupt latch and enable bits */
1436 ulpi_write(otg, 0x1F, 0x92);
1437 ulpi_write(otg, 0x1F, 0x95);
1438 break;
1439 default:
1440 break;
1441 }
1442
1443 /* put the controller in normal mode */
1444 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1445 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1446 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1447 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1448}
1449
Anji jonnalad270e2d2011-08-09 11:28:32 +05301450static const char *chg_to_string(enum usb_chg_type chg_type)
1451{
1452 switch (chg_type) {
1453 case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
1454 case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
1455 case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
1456 case USB_ACA_A_CHARGER: return "USB_ACA_A_CHARGER";
1457 case USB_ACA_B_CHARGER: return "USB_ACA_B_CHARGER";
1458 case USB_ACA_C_CHARGER: return "USB_ACA_C_CHARGER";
1459 case USB_ACA_DOCK_CHARGER: return "USB_ACA_DOCK_CHARGER";
1460 default: return "INVALID_CHARGER";
1461 }
1462}
1463
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301464#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1465#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
1466#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
1467#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
1468static void msm_chg_detect_work(struct work_struct *w)
1469{
1470 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1471 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001472 bool is_dcd, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301473 unsigned long delay;
1474
1475 dev_dbg(otg->dev, "chg detection work\n");
1476 switch (motg->chg_state) {
1477 case USB_CHG_STATE_UNDEFINED:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301478 msm_chg_block_on(motg);
1479 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001480 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301481 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1482 motg->dcd_retries = 0;
1483 delay = MSM_CHG_DCD_POLL_TIME;
1484 break;
1485 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001486 is_aca = msm_chg_aca_detect(motg);
1487 if (is_aca) {
1488 /*
1489 * ID_A can be ACA dock too. continue
1490 * primary detection after DCD.
1491 */
1492 if (test_bit(ID_A, &motg->inputs)) {
1493 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1494 } else {
1495 delay = 0;
1496 break;
1497 }
1498 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301499 is_dcd = msm_chg_check_dcd(motg);
1500 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1501 if (is_dcd || tmout) {
1502 msm_chg_disable_dcd(motg);
1503 msm_chg_enable_primary_det(motg);
1504 delay = MSM_CHG_PRIMARY_DET_TIME;
1505 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1506 } else {
1507 delay = MSM_CHG_DCD_POLL_TIME;
1508 }
1509 break;
1510 case USB_CHG_STATE_DCD_DONE:
1511 vout = msm_chg_check_primary_det(motg);
1512 if (vout) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301513 if (test_bit(ID_A, &motg->inputs)) {
1514 motg->chg_type = USB_ACA_DOCK_CHARGER;
1515 motg->chg_state = USB_CHG_STATE_DETECTED;
1516 delay = 0;
1517 break;
1518 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301519 msm_chg_enable_secondary_det(motg);
1520 delay = MSM_CHG_SECONDARY_DET_TIME;
1521 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1522 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301523 if (test_bit(ID_A, &motg->inputs)) {
1524 motg->chg_type = USB_ACA_A_CHARGER;
1525 motg->chg_state = USB_CHG_STATE_DETECTED;
1526 delay = 0;
1527 break;
1528 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301529 motg->chg_type = USB_SDP_CHARGER;
1530 motg->chg_state = USB_CHG_STATE_DETECTED;
1531 delay = 0;
1532 }
1533 break;
1534 case USB_CHG_STATE_PRIMARY_DONE:
1535 vout = msm_chg_check_secondary_det(motg);
1536 if (vout)
1537 motg->chg_type = USB_DCP_CHARGER;
1538 else
1539 motg->chg_type = USB_CDP_CHARGER;
1540 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1541 /* fall through */
1542 case USB_CHG_STATE_SECONDARY_DONE:
1543 motg->chg_state = USB_CHG_STATE_DETECTED;
1544 case USB_CHG_STATE_DETECTED:
1545 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001546 msm_chg_enable_aca_det(motg);
1547 msm_chg_enable_aca_intr(motg);
Anji jonnalad270e2d2011-08-09 11:28:32 +05301548 dev_dbg(otg->dev, "chg_type = %s\n",
1549 chg_to_string(motg->chg_type));
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301550 schedule_work(&motg->sm_work);
1551 return;
1552 default:
1553 return;
1554 }
1555
1556 schedule_delayed_work(&motg->chg_work, delay);
1557}
1558
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301559/*
1560 * We support OTG, Peripheral only and Host only configurations. In case
1561 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1562 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1563 * enabled when switch is controlled by user and default mode is supplied
1564 * by board file, which can be changed by userspace later.
1565 */
1566static void msm_otg_init_sm(struct msm_otg *motg)
1567{
1568 struct msm_otg_platform_data *pdata = motg->pdata;
1569 u32 otgsc = readl(USB_OTGSC);
1570
1571 switch (pdata->mode) {
1572 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001573 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301574 if (pdata->default_mode == USB_HOST) {
1575 clear_bit(ID, &motg->inputs);
1576 } else if (pdata->default_mode == USB_PERIPHERAL) {
1577 set_bit(ID, &motg->inputs);
1578 set_bit(B_SESS_VLD, &motg->inputs);
1579 } else {
1580 set_bit(ID, &motg->inputs);
1581 clear_bit(B_SESS_VLD, &motg->inputs);
1582 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001583 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301584 if (aca_enabled()) {
1585 if (irq_read_line(motg->pdata->pmic_id_irq))
1586 set_bit(ID, &motg->inputs);
1587 else
1588 clear_bit(ID, &motg->inputs);
1589
1590 } else {
1591 if (otgsc & OTGSC_ID)
1592 set_bit(ID, &motg->inputs);
1593 else
1594 clear_bit(ID, &motg->inputs);
1595 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001596
1597 if (otgsc & OTGSC_BSV)
1598 set_bit(B_SESS_VLD, &motg->inputs);
1599 else
1600 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301601 }
1602 break;
1603 case USB_HOST:
1604 clear_bit(ID, &motg->inputs);
1605 break;
1606 case USB_PERIPHERAL:
1607 set_bit(ID, &motg->inputs);
1608 if (otgsc & OTGSC_BSV)
1609 set_bit(B_SESS_VLD, &motg->inputs);
1610 else
1611 clear_bit(B_SESS_VLD, &motg->inputs);
1612 break;
1613 default:
1614 break;
1615 }
1616}
1617
1618static void msm_otg_sm_work(struct work_struct *w)
1619{
1620 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
1621 struct otg_transceiver *otg = &motg->otg;
1622
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301623 pm_runtime_resume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301624 switch (otg->state) {
1625 case OTG_STATE_UNDEFINED:
1626 dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
1627 msm_otg_reset(otg);
1628 msm_otg_init_sm(motg);
1629 otg->state = OTG_STATE_B_IDLE;
1630 /* FALL THROUGH */
1631 case OTG_STATE_B_IDLE:
1632 dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001633 if ((!test_bit(ID, &motg->inputs) ||
1634 test_bit(ID_A, &motg->inputs)) && otg->host) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001635 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
1636 msm_otg_notify_charger(motg,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301637 IDEV_ACA_CHG_MAX);
1638 else if (test_bit(ID_A, &motg->inputs))
1639 msm_otg_notify_charger(motg,
1640 IDEV_ACA_CHG_MAX - IUNIT);
1641 else if (motg->pdata->vbus_power)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001642 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301643 msm_otg_start_host(otg, 1);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301644 /*
1645 * Link can not generate PHY_ALT interrupt
1646 * in host mode when no device is attached
1647 * to the port. It is also observed PHY_ALT
1648 * interrupt missing upon Micro-A cable disconnect.
1649 * Hence disable PHY_ALT interrupt and perform
1650 * polling to detect RID change.
1651 */
1652 msm_chg_enable_aca_det(motg);
1653 msm_chg_disable_aca_intr(motg);
1654 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301655 otg->state = OTG_STATE_A_HOST;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301656 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1657 switch (motg->chg_state) {
1658 case USB_CHG_STATE_UNDEFINED:
1659 msm_chg_detect_work(&motg->chg_work.work);
1660 break;
1661 case USB_CHG_STATE_DETECTED:
1662 switch (motg->chg_type) {
1663 case USB_DCP_CHARGER:
1664 msm_otg_notify_charger(motg,
1665 IDEV_CHG_MAX);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301666 pm_runtime_put_noidle(otg->dev);
1667 pm_runtime_suspend(otg->dev);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301668 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301669 case USB_ACA_B_CHARGER:
1670 msm_otg_notify_charger(motg,
1671 IDEV_ACA_CHG_MAX);
1672 /*
1673 * (ID_B --> ID_C) PHY_ALT interrupt can
1674 * not be detected in LPM.
1675 */
1676 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301677 case USB_CDP_CHARGER:
1678 msm_otg_notify_charger(motg,
1679 IDEV_CHG_MAX);
1680 msm_otg_start_peripheral(otg, 1);
1681 otg->state = OTG_STATE_B_PERIPHERAL;
1682 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301683 case USB_ACA_C_CHARGER:
1684 msm_otg_notify_charger(motg,
1685 IDEV_ACA_CHG_MAX);
1686 msm_otg_start_peripheral(otg, 1);
1687 otg->state = OTG_STATE_B_PERIPHERAL;
1688 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301689 case USB_SDP_CHARGER:
1690 msm_otg_notify_charger(motg, IUNIT);
1691 msm_otg_start_peripheral(otg, 1);
1692 otg->state = OTG_STATE_B_PERIPHERAL;
1693 break;
1694 default:
1695 break;
1696 }
1697 break;
1698 default:
1699 break;
1700 }
1701 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301702 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301703 msm_otg_notify_charger(motg, 0);
1704 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1705 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301706 msm_otg_reset(otg);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301707 pm_runtime_put_noidle(otg->dev);
1708 pm_runtime_suspend(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301709 }
1710 break;
1711 case OTG_STATE_B_PERIPHERAL:
1712 dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
1713 if (!test_bit(B_SESS_VLD, &motg->inputs) ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001714 !test_bit(ID, &motg->inputs) ||
1715 !test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301716 msm_otg_start_peripheral(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001717 otg->state = OTG_STATE_B_IDLE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001718 schedule_work(w);
1719 } else if (test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301720 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001721 }
1722 break;
1723 case OTG_STATE_A_HOST:
1724 dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
1725 if (test_bit(ID, &motg->inputs) &&
1726 !test_bit(ID_A, &motg->inputs)) {
1727 msm_otg_start_host(otg, 0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301728 if (motg->pdata->vbus_power) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001729 motg->pdata->vbus_power(0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301730 msleep(100); /* TA_WAIT_VFALL */
1731 }
1732 /*
1733 * Exit point of host mode.
1734 *
1735 * 1. Micro-A cable disconnect: Just schedule
1736 * the work. PHY is reset in B_IDLE and LPM
1737 * is allowed.
1738 * 2. ID_GND --> ID_B: No need to reset the PHY.
1739 * HCD core clears all PORTSC bits and initializes
1740 * the controller to host mode in remove_hcd.
1741 * Restore PORTSC transceiver select bits (ULPI)
1742 * and reset the controller to change MODE bits.
1743 * PHY_ALT interrupt can not occur in host mode.
1744 */
1745 del_timer_sync(&motg->id_timer);
1746 if (motg->chg_state != USB_CHG_STATE_UNDEFINED) {
1747 msm_otg_link_reset(motg);
1748 msm_chg_enable_aca_intr(motg);
1749 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301750 otg->state = OTG_STATE_B_IDLE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301751 schedule_work(w);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001752 } else if (test_bit(ID_A, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001753 if (motg->pdata->vbus_power)
1754 motg->pdata->vbus_power(0);
1755 msm_otg_notify_charger(motg,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301756 IDEV_ACA_CHG_MAX - motg->mA_port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001757 } else if (!test_bit(ID, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001758 msm_otg_notify_charger(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001759 if (motg->pdata->vbus_power)
1760 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301761 }
1762 break;
1763 default:
1764 break;
1765 }
1766}
1767
1768static irqreturn_t msm_otg_irq(int irq, void *data)
1769{
1770 struct msm_otg *motg = data;
1771 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001772 u32 otgsc = 0, usbsts;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301773
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301774 if (atomic_read(&motg->in_lpm)) {
1775 disable_irq_nosync(irq);
1776 motg->async_int = 1;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301777 pm_request_resume(otg->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301778 return IRQ_HANDLED;
1779 }
1780
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001781 usbsts = readl(USB_USBSTS);
1782 if ((usbsts & PHY_ALT_INT)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301783 dev_dbg(otg->dev, "PHY_ALT interrupt\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001784 writel(PHY_ALT_INT, USB_USBSTS);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301785 if (msm_chg_check_aca_intr(motg)) {
1786 dev_dbg(otg->dev, "ACA work from IRQ\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001787 schedule_work(&motg->sm_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301788 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001789 return IRQ_HANDLED;
1790 }
1791
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301792 otgsc = readl(USB_OTGSC);
1793 if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1794 return IRQ_NONE;
1795
1796 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301797 if (otgsc & OTGSC_ID) {
1798 dev_dbg(otg->dev, "ID set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301799 set_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301800 } else {
1801 dev_dbg(otg->dev, "ID clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301802 clear_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301803 msm_chg_enable_aca_det(motg);
1804 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001805 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301806 } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301807 if (otgsc & OTGSC_BSV) {
1808 dev_dbg(otg->dev, "BSV set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301809 set_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301810 } else {
1811 dev_dbg(otg->dev, "BSV clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301812 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301813 msm_chg_check_aca_intr(motg);
1814 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001815 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301816 }
1817
1818 writel(otgsc, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001819 return IRQ_HANDLED;
1820}
1821
1822static void msm_otg_set_vbus_state(int online)
1823{
1824 struct msm_otg *motg = the_msm_otg;
1825
1826 /* We depend on PMIC for only VBUS ON interrupt */
1827 if (!atomic_read(&motg->in_lpm) || !online)
1828 return;
1829
1830 /*
1831 * Let interrupt handler take care of resuming
1832 * the hardware.
1833 */
1834 msm_otg_irq(motg->irq, (void *) motg);
1835}
1836
1837static irqreturn_t msm_pmic_id_irq(int irq, void *data)
1838{
1839 struct msm_otg *motg = data;
1840
1841 if (atomic_read(&motg->in_lpm) && !motg->async_int)
1842 msm_otg_irq(motg->irq, motg);
1843
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301844 return IRQ_HANDLED;
1845}
1846
1847static int msm_otg_mode_show(struct seq_file *s, void *unused)
1848{
1849 struct msm_otg *motg = s->private;
1850 struct otg_transceiver *otg = &motg->otg;
1851
1852 switch (otg->state) {
1853 case OTG_STATE_A_HOST:
1854 seq_printf(s, "host\n");
1855 break;
1856 case OTG_STATE_B_PERIPHERAL:
1857 seq_printf(s, "peripheral\n");
1858 break;
1859 default:
1860 seq_printf(s, "none\n");
1861 break;
1862 }
1863
1864 return 0;
1865}
1866
1867static int msm_otg_mode_open(struct inode *inode, struct file *file)
1868{
1869 return single_open(file, msm_otg_mode_show, inode->i_private);
1870}
1871
1872static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1873 size_t count, loff_t *ppos)
1874{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05301875 struct seq_file *s = file->private_data;
1876 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301877 char buf[16];
1878 struct otg_transceiver *otg = &motg->otg;
1879 int status = count;
1880 enum usb_mode_type req_mode;
1881
1882 memset(buf, 0x00, sizeof(buf));
1883
1884 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1885 status = -EFAULT;
1886 goto out;
1887 }
1888
1889 if (!strncmp(buf, "host", 4)) {
1890 req_mode = USB_HOST;
1891 } else if (!strncmp(buf, "peripheral", 10)) {
1892 req_mode = USB_PERIPHERAL;
1893 } else if (!strncmp(buf, "none", 4)) {
1894 req_mode = USB_NONE;
1895 } else {
1896 status = -EINVAL;
1897 goto out;
1898 }
1899
1900 switch (req_mode) {
1901 case USB_NONE:
1902 switch (otg->state) {
1903 case OTG_STATE_A_HOST:
1904 case OTG_STATE_B_PERIPHERAL:
1905 set_bit(ID, &motg->inputs);
1906 clear_bit(B_SESS_VLD, &motg->inputs);
1907 break;
1908 default:
1909 goto out;
1910 }
1911 break;
1912 case USB_PERIPHERAL:
1913 switch (otg->state) {
1914 case OTG_STATE_B_IDLE:
1915 case OTG_STATE_A_HOST:
1916 set_bit(ID, &motg->inputs);
1917 set_bit(B_SESS_VLD, &motg->inputs);
1918 break;
1919 default:
1920 goto out;
1921 }
1922 break;
1923 case USB_HOST:
1924 switch (otg->state) {
1925 case OTG_STATE_B_IDLE:
1926 case OTG_STATE_B_PERIPHERAL:
1927 clear_bit(ID, &motg->inputs);
1928 break;
1929 default:
1930 goto out;
1931 }
1932 break;
1933 default:
1934 goto out;
1935 }
1936
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301937 pm_runtime_resume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301938 schedule_work(&motg->sm_work);
1939out:
1940 return status;
1941}
1942
1943const struct file_operations msm_otg_mode_fops = {
1944 .open = msm_otg_mode_open,
1945 .read = seq_read,
1946 .write = msm_otg_mode_write,
1947 .llseek = seq_lseek,
1948 .release = single_release,
1949};
1950
Anji jonnalad270e2d2011-08-09 11:28:32 +05301951static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
1952{
1953 struct msm_otg *motg = s->private;
1954
1955 seq_printf(s, chg_to_string(motg->chg_type));
1956 return 0;
1957}
1958
1959static int msm_otg_chg_open(struct inode *inode, struct file *file)
1960{
1961 return single_open(file, msm_otg_show_chg_type, inode->i_private);
1962}
1963
1964const struct file_operations msm_otg_chg_fops = {
1965 .open = msm_otg_chg_open,
1966 .read = seq_read,
1967 .llseek = seq_lseek,
1968 .release = single_release,
1969};
1970
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301971static int msm_otg_aca_show(struct seq_file *s, void *unused)
1972{
1973 if (debug_aca_enabled)
1974 seq_printf(s, "enabled\n");
1975 else
1976 seq_printf(s, "disabled\n");
1977
1978 return 0;
1979}
1980
1981static int msm_otg_aca_open(struct inode *inode, struct file *file)
1982{
1983 return single_open(file, msm_otg_aca_show, inode->i_private);
1984}
1985
1986static ssize_t msm_otg_aca_write(struct file *file, const char __user *ubuf,
1987 size_t count, loff_t *ppos)
1988{
1989 char buf[8];
1990
1991 memset(buf, 0x00, sizeof(buf));
1992
1993 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1994 return -EFAULT;
1995
1996 if (!strncmp(buf, "enable", 6))
1997 debug_aca_enabled = true;
1998 else
1999 debug_aca_enabled = false;
2000
2001 return count;
2002}
2003
2004const struct file_operations msm_otg_aca_fops = {
2005 .open = msm_otg_aca_open,
2006 .read = seq_read,
2007 .write = msm_otg_aca_write,
2008 .llseek = seq_lseek,
2009 .release = single_release,
2010};
2011
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302012static struct dentry *msm_otg_dbg_root;
2013static struct dentry *msm_otg_dbg_mode;
Anji jonnalad270e2d2011-08-09 11:28:32 +05302014static struct dentry *msm_otg_chg_type;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302015static struct dentry *msm_otg_dbg_aca;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302016
2017static int msm_otg_debugfs_init(struct msm_otg *motg)
2018{
Anji jonnalad270e2d2011-08-09 11:28:32 +05302019
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302020 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
2021
2022 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
2023 return -ENODEV;
2024
Anji jonnalad270e2d2011-08-09 11:28:32 +05302025 if (motg->pdata->mode == USB_OTG &&
2026 motg->pdata->otg_control == OTG_USER_CONTROL) {
2027
2028 msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
2029 S_IWUSR, msm_otg_dbg_root, motg,
2030 &msm_otg_mode_fops);
2031
2032 if (!msm_otg_dbg_mode) {
2033 debugfs_remove(msm_otg_dbg_root);
2034 msm_otg_dbg_root = NULL;
2035 return -ENODEV;
2036 }
2037 }
2038
2039 msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
2040 msm_otg_dbg_root, motg,
2041 &msm_otg_chg_fops);
2042
2043 if (!msm_otg_chg_type) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302044 debugfs_remove_recursive(msm_otg_dbg_root);
2045 return -ENODEV;
2046 }
2047
2048 msm_otg_dbg_aca = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
2049 msm_otg_dbg_root, motg,
2050 &msm_otg_aca_fops);
2051
2052 if (!msm_otg_dbg_aca) {
2053 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302054 return -ENODEV;
2055 }
2056
2057 return 0;
2058}
2059
2060static void msm_otg_debugfs_cleanup(void)
2061{
Anji jonnalad270e2d2011-08-09 11:28:32 +05302062 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302063}
2064
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302065static u64 msm_otg_dma_mask = DMA_BIT_MASK(64);
2066static struct platform_device *msm_otg_add_pdev(
2067 struct platform_device *ofdev, const char *name)
2068{
2069 struct platform_device *pdev;
2070 const struct resource *res = ofdev->resource;
2071 unsigned int num = ofdev->num_resources;
2072 int retval;
2073
2074 pdev = platform_device_alloc(name, -1);
2075 if (!pdev) {
2076 retval = -ENOMEM;
2077 goto error;
2078 }
2079
2080 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
2081 pdev->dev.dma_mask = &msm_otg_dma_mask;
2082
2083 if (num) {
2084 retval = platform_device_add_resources(pdev, res, num);
2085 if (retval)
2086 goto error;
2087 }
2088
2089 retval = platform_device_add(pdev);
2090 if (retval)
2091 goto error;
2092
2093 return pdev;
2094
2095error:
2096 platform_device_put(pdev);
2097 return ERR_PTR(retval);
2098}
2099
2100static int msm_otg_setup_devices(struct platform_device *ofdev,
2101 enum usb_mode_type mode, bool init)
2102{
2103 const char *gadget_name = "msm_hsusb";
2104 const char *host_name = "msm_hsusb_host";
2105 static struct platform_device *gadget_pdev;
2106 static struct platform_device *host_pdev;
2107 int retval = 0;
2108
2109 if (!init) {
2110 if (gadget_pdev)
2111 platform_device_unregister(gadget_pdev);
2112 if (host_pdev)
2113 platform_device_unregister(host_pdev);
2114 return 0;
2115 }
2116
2117 switch (mode) {
2118 case USB_OTG:
2119 /* fall through */
2120 case USB_PERIPHERAL:
2121 gadget_pdev = msm_otg_add_pdev(ofdev, gadget_name);
2122 if (IS_ERR(gadget_pdev)) {
2123 retval = PTR_ERR(gadget_pdev);
2124 break;
2125 }
2126 if (mode == USB_PERIPHERAL)
2127 break;
2128 /* fall through */
2129 case USB_HOST:
2130 host_pdev = msm_otg_add_pdev(ofdev, host_name);
2131 if (IS_ERR(host_pdev)) {
2132 retval = PTR_ERR(host_pdev);
2133 if (mode == USB_OTG)
2134 platform_device_unregister(gadget_pdev);
2135 }
2136 break;
2137 default:
2138 break;
2139 }
2140
2141 return retval;
2142}
2143
2144struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
2145{
2146 struct device_node *node = pdev->dev.of_node;
2147 struct msm_otg_platform_data *pdata;
2148 int len = 0;
2149
2150 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
2151 if (!pdata) {
2152 pr_err("unable to allocate platform data\n");
2153 return NULL;
2154 }
2155 of_get_property(node, "qcom,hsusb-otg-phy-init-seq", &len);
2156 if (len) {
2157 pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
2158 if (!pdata->phy_init_seq)
2159 return NULL;
2160 of_property_read_u32_array(node, "qcom,hsusb-otg-phy-init-seq",
2161 pdata->phy_init_seq,
2162 len/sizeof(*pdata->phy_init_seq));
2163 }
2164 of_property_read_u32(node, "qcom,hsusb-otg-power-budget",
2165 &pdata->power_budget);
2166 of_property_read_u32(node, "qcom,hsusb-otg-mode",
2167 &pdata->mode);
2168 of_property_read_u32(node, "qcom,hsusb-otg-otg-control",
2169 &pdata->otg_control);
2170 of_property_read_u32(node, "qcom,hsusb-otg-default-mode",
2171 &pdata->default_mode);
2172 of_property_read_u32(node, "qcom,hsusb-otg-phy-type",
2173 &pdata->phy_type);
2174 of_property_read_u32(node, "qcom,hsusb-otg-pmic-id-irq",
2175 &pdata->pmic_id_irq);
2176 of_property_read_string(node, "qcom,hsusb-otg-pclk-src-name",
2177 &pdata->pclk_src_name);
2178 return pdata;
2179}
2180
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302181static int __init msm_otg_probe(struct platform_device *pdev)
2182{
2183 int ret = 0;
2184 struct resource *res;
2185 struct msm_otg *motg;
2186 struct otg_transceiver *otg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302187 struct msm_otg_platform_data *pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302188
2189 dev_info(&pdev->dev, "msm_otg probe\n");
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302190
2191 if (pdev->dev.of_node) {
2192 dev_dbg(&pdev->dev, "device tree enabled\n");
2193 pdata = msm_otg_dt_to_pdata(pdev);
2194 if (!pdata)
2195 return -ENOMEM;
2196 ret = msm_otg_setup_devices(pdev, pdata->mode, true);
2197 if (ret) {
2198 dev_err(&pdev->dev, "devices setup failed\n");
2199 return ret;
2200 }
2201 } else if (!pdev->dev.platform_data) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302202 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
2203 return -ENODEV;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302204 } else {
2205 pdata = pdev->dev.platform_data;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302206 }
2207
2208 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
2209 if (!motg) {
2210 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
2211 return -ENOMEM;
2212 }
2213
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002214 the_msm_otg = motg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302215 motg->pdata = pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302216 otg = &motg->otg;
2217 otg->dev = &pdev->dev;
2218
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302219 /*
2220 * ACA ID_GND threshold range is overlapped with OTG ID_FLOAT. Hence
2221 * PHY treat ACA ID_GND as float and no interrupt is generated. But
2222 * PMIC can detect ACA ID_GND and generate an interrupt.
2223 */
2224 if (aca_enabled() && motg->pdata->otg_control != OTG_PMIC_CONTROL) {
2225 dev_err(&pdev->dev, "ACA can not be enabled without PMIC\n");
2226 ret = -EINVAL;
2227 goto free_motg;
2228 }
2229
Amit Blay02eff132011-09-21 16:46:24 +03002230 /* Some targets don't support PHY clock. */
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302231 motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
Amit Blay02eff132011-09-21 16:46:24 +03002232 if (IS_ERR(motg->phy_reset_clk))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302233 dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302234
2235 motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
2236 if (IS_ERR(motg->clk)) {
2237 dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
2238 ret = PTR_ERR(motg->clk);
2239 goto put_phy_reset_clk;
2240 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302241 clk_set_rate(motg->clk, 60000000);
2242
2243 /*
2244 * If USB Core is running its protocol engine based on CORE CLK,
2245 * CORE CLK must be running at >55Mhz for correct HSUSB
2246 * operation and USB core cannot tolerate frequency changes on
2247 * CORE CLK. For such USB cores, vote for maximum clk frequency
2248 * on pclk source
2249 */
2250 if (motg->pdata->pclk_src_name) {
2251 motg->pclk_src = clk_get(&pdev->dev,
2252 motg->pdata->pclk_src_name);
2253 if (IS_ERR(motg->pclk_src))
2254 goto put_clk;
2255 clk_set_rate(motg->pclk_src, INT_MAX);
2256 clk_enable(motg->pclk_src);
2257 } else
2258 motg->pclk_src = ERR_PTR(-ENOENT);
2259
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302260 motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
2261 if (IS_ERR(motg->pclk)) {
2262 dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
2263 ret = PTR_ERR(motg->pclk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302264 goto put_pclk_src;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302265 }
2266
Amit Blay02eff132011-09-21 16:46:24 +03002267 motg->system_clk = clk_get(&pdev->dev, "usb_hs_system_clk");
2268 if (!IS_ERR(motg->system_clk))
2269 clk_enable(motg->system_clk);
2270
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302271 /*
2272 * USB core clock is not present on all MSM chips. This
2273 * clock is introduced to remove the dependency on AXI
2274 * bus frequency.
2275 */
2276 motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
2277 if (IS_ERR(motg->core_clk))
2278 motg->core_clk = NULL;
2279
2280 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2281 if (!res) {
2282 dev_err(&pdev->dev, "failed to get platform resource mem\n");
2283 ret = -ENODEV;
2284 goto put_core_clk;
2285 }
2286
2287 motg->regs = ioremap(res->start, resource_size(res));
2288 if (!motg->regs) {
2289 dev_err(&pdev->dev, "ioremap failed\n");
2290 ret = -ENOMEM;
2291 goto put_core_clk;
2292 }
2293 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
2294
2295 motg->irq = platform_get_irq(pdev, 0);
2296 if (!motg->irq) {
2297 dev_err(&pdev->dev, "platform_get_irq failed\n");
2298 ret = -ENODEV;
2299 goto free_regs;
2300 }
2301
Anji jonnala7da3f262011-12-02 17:22:14 -08002302 motg->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, "usb");
2303 if (IS_ERR(motg->xo_handle)) {
2304 dev_err(&pdev->dev, "%s not able to get the handle "
2305 "to vote for TCXO D0 buffer\n", __func__);
2306 ret = PTR_ERR(motg->xo_handle);
2307 goto free_regs;
2308 }
2309
2310 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
2311 if (ret) {
2312 dev_err(&pdev->dev, "%s failed to vote for TCXO "
2313 "D0 buffer%d\n", __func__, ret);
2314 goto free_xo_handle;
2315 }
2316
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302317 clk_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302318
2319 ret = msm_hsusb_init_vddcx(motg, 1);
2320 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002321 dev_err(&pdev->dev, "hsusb vddcx init failed\n");
Anji jonnala7da3f262011-12-02 17:22:14 -08002322 goto devote_xo_handle;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302323 }
2324
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002325 ret = msm_hsusb_config_vddcx(1);
2326 if (ret) {
2327 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
2328 goto free_init_vddcx;
2329 }
2330
Anji jonnala11aa5c42011-05-04 10:19:48 +05302331 ret = msm_hsusb_ldo_init(motg, 1);
2332 if (ret) {
2333 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002334 goto free_init_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302335 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002336
2337 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302338 if (ret) {
2339 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002340 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302341 }
2342
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302343 if (motg->core_clk)
2344 clk_enable(motg->core_clk);
2345
2346 writel(0, USB_USBINTR);
2347 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002348 /* Ensure that above STOREs are completed before enabling interrupts */
2349 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302350
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002351 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302352 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302353 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302354 setup_timer(&motg->id_timer, msm_otg_id_timer_func,
2355 (unsigned long) motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302356 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
2357 "msm_otg", motg);
2358 if (ret) {
2359 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002360 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302361 }
2362
2363 otg->init = msm_otg_reset;
2364 otg->set_host = msm_otg_set_host;
2365 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302366 otg->set_power = msm_otg_set_power;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302367 otg->set_suspend = msm_otg_set_suspend;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302368
2369 otg->io_ops = &msm_otg_io_ops;
2370
2371 ret = otg_set_transceiver(&motg->otg);
2372 if (ret) {
2373 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
2374 goto free_irq;
2375 }
2376
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002377 if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
2378 if (motg->pdata->pmic_id_irq) {
2379 ret = request_irq(motg->pdata->pmic_id_irq,
2380 msm_pmic_id_irq,
2381 IRQF_TRIGGER_RISING |
2382 IRQF_TRIGGER_FALLING,
2383 "msm_otg", motg);
2384 if (ret) {
2385 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
2386 goto remove_otg;
2387 }
2388 } else {
2389 ret = -ENODEV;
2390 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
2391 goto remove_otg;
2392 }
2393 }
2394
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302395 msm_hsusb_mhl_switch_enable(motg, 1);
2396
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302397 platform_set_drvdata(pdev, motg);
2398 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002399 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302400
Anji jonnalad270e2d2011-08-09 11:28:32 +05302401 ret = msm_otg_debugfs_init(motg);
2402 if (ret)
2403 dev_dbg(&pdev->dev, "mode debugfs file is"
2404 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302405
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002406 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2407 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
2408
Amit Blay58b31472011-11-18 09:39:39 +02002409 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
2410 if (motg->pdata->otg_control == OTG_PMIC_CONTROL &&
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002411 motg->pdata->pmic_id_irq)
Amit Blay58b31472011-11-18 09:39:39 +02002412 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002413 ALLOW_PHY_RETENTION |
2414 ALLOW_PHY_COMP_DISABLE;
2415
Amit Blay58b31472011-11-18 09:39:39 +02002416 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
2417 motg->caps = ALLOW_PHY_RETENTION;
2418 }
2419
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002420 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302421 pm_runtime_set_active(&pdev->dev);
2422 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302423
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302424 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002425
2426remove_otg:
2427 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302428free_irq:
2429 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002430destroy_wlock:
2431 wake_lock_destroy(&motg->wlock);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302432 clk_disable(motg->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002433 msm_hsusb_ldo_enable(motg, 0);
2434free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302435 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002436free_init_vddcx:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302437 msm_hsusb_init_vddcx(motg, 0);
Anji jonnala7da3f262011-12-02 17:22:14 -08002438devote_xo_handle:
2439 msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
2440free_xo_handle:
2441 msm_xo_put(motg->xo_handle);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302442free_regs:
2443 iounmap(motg->regs);
2444put_core_clk:
2445 if (motg->core_clk)
2446 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002447
2448 if (!IS_ERR(motg->system_clk)) {
2449 clk_disable(motg->system_clk);
2450 clk_put(motg->system_clk);
2451 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302452put_pclk_src:
2453 if (!IS_ERR(motg->pclk_src)) {
2454 clk_disable(motg->pclk_src);
2455 clk_put(motg->pclk_src);
2456 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302457put_clk:
2458 clk_put(motg->clk);
2459put_phy_reset_clk:
Amit Blay02eff132011-09-21 16:46:24 +03002460 if (!IS_ERR(motg->phy_reset_clk))
2461 clk_put(motg->phy_reset_clk);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302462free_motg:
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302463 kfree(motg);
2464 return ret;
2465}
2466
2467static int __devexit msm_otg_remove(struct platform_device *pdev)
2468{
2469 struct msm_otg *motg = platform_get_drvdata(pdev);
2470 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302471 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302472
2473 if (otg->host || otg->gadget)
2474 return -EBUSY;
2475
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302476 if (pdev->dev.of_node)
2477 msm_otg_setup_devices(pdev, motg->pdata->mode, false);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002478 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2479 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302480 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302481 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302482 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302483
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302484 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302485
2486 device_init_wakeup(&pdev->dev, 0);
2487 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002488 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302489
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302490 msm_hsusb_mhl_switch_enable(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002491 if (motg->pdata->pmic_id_irq)
2492 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302493 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302494 free_irq(motg->irq, motg);
2495
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302496 /*
2497 * Put PHY in low power mode.
2498 */
2499 ulpi_read(otg, 0x14);
2500 ulpi_write(otg, 0x08, 0x09);
2501
2502 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
2503 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
2504 if (readl(USB_PORTSC) & PORTSC_PHCD)
2505 break;
2506 udelay(1);
2507 cnt++;
2508 }
2509 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
2510 dev_err(otg->dev, "Unable to suspend PHY\n");
2511
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302512 clk_disable(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302513 if (motg->core_clk)
2514 clk_disable(motg->core_clk);
Amit Blay137575f2011-11-06 15:20:54 +02002515 if (!IS_ERR(motg->system_clk))
2516 clk_disable(motg->system_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302517 if (!IS_ERR(motg->pclk_src)) {
2518 clk_disable(motg->pclk_src);
2519 clk_put(motg->pclk_src);
2520 }
Anji jonnala7da3f262011-12-02 17:22:14 -08002521 msm_xo_put(motg->xo_handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002522 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302523 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002524 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302525
2526 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302527 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302528
Amit Blay02eff132011-09-21 16:46:24 +03002529 if (!IS_ERR(motg->phy_reset_clk))
2530 clk_put(motg->phy_reset_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302531 clk_put(motg->pclk);
2532 clk_put(motg->clk);
2533 if (motg->core_clk)
2534 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002535 if (!IS_ERR(motg->system_clk))
2536 clk_put(motg->system_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302537
2538 kfree(motg);
2539
2540 return 0;
2541}
2542
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302543#ifdef CONFIG_PM_RUNTIME
2544static int msm_otg_runtime_idle(struct device *dev)
2545{
2546 struct msm_otg *motg = dev_get_drvdata(dev);
2547 struct otg_transceiver *otg = &motg->otg;
2548
2549 dev_dbg(dev, "OTG runtime idle\n");
2550
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302551 if (otg->state == OTG_STATE_UNDEFINED)
2552 return -EAGAIN;
2553 else
2554 return 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302555}
2556
2557static int msm_otg_runtime_suspend(struct device *dev)
2558{
2559 struct msm_otg *motg = dev_get_drvdata(dev);
2560
2561 dev_dbg(dev, "OTG runtime suspend\n");
2562 return msm_otg_suspend(motg);
2563}
2564
2565static int msm_otg_runtime_resume(struct device *dev)
2566{
2567 struct msm_otg *motg = dev_get_drvdata(dev);
2568
2569 dev_dbg(dev, "OTG runtime resume\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302570 pm_runtime_get_noresume(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302571 return msm_otg_resume(motg);
2572}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302573#endif
2574
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302575#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302576static int msm_otg_pm_suspend(struct device *dev)
2577{
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302578 int ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302579
2580 dev_dbg(dev, "OTG PM suspend\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302581
2582#ifdef CONFIG_PM_RUNTIME
2583 ret = pm_runtime_suspend(dev);
2584 if (ret > 0)
2585 ret = 0;
2586#else
2587 ret = msm_otg_suspend(dev_get_drvdata(dev));
2588#endif
2589 return ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302590}
2591
2592static int msm_otg_pm_resume(struct device *dev)
2593{
2594 struct msm_otg *motg = dev_get_drvdata(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302595
2596 dev_dbg(dev, "OTG PM resume\n");
2597
Manu Gautamf284c052011-09-08 16:52:48 +05302598#ifdef CONFIG_PM_RUNTIME
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302599 /*
Manu Gautamf284c052011-09-08 16:52:48 +05302600 * Do not resume hardware as part of system resume,
2601 * rather, wait for the ASYNC INT from the h/w
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302602 */
Gregory Beanebd8ca22011-10-11 12:02:35 -07002603 return 0;
Manu Gautamf284c052011-09-08 16:52:48 +05302604#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302605
Manu Gautamf284c052011-09-08 16:52:48 +05302606 return msm_otg_resume(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302607}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302608#endif
2609
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302610#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302611static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302612 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
2613 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
2614 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302615};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302616#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302617
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302618static struct of_device_id msm_otg_dt_match[] = {
2619 { .compatible = "qcom,hsusb-otg",
2620 },
2621 {}
2622};
2623
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302624static struct platform_driver msm_otg_driver = {
2625 .remove = __devexit_p(msm_otg_remove),
2626 .driver = {
2627 .name = DRIVER_NAME,
2628 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302629#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302630 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302631#endif
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05302632 .of_match_table = msm_otg_dt_match,
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302633 },
2634};
2635
2636static int __init msm_otg_init(void)
2637{
2638 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
2639}
2640
2641static void __exit msm_otg_exit(void)
2642{
2643 platform_driver_unregister(&msm_otg_driver);
2644}
2645
2646module_init(msm_otg_init);
2647module_exit(msm_otg_exit);
2648
2649MODULE_LICENSE("GPL v2");
2650MODULE_DESCRIPTION("MSM USB transceiver driver");