blob: 2da48ab4d5048d2406f3618c98493f650a4f5028 [file] [log] [blame]
Manu Gautam5143b252012-01-05 19:25:23 -08001/* Copyright (c) 2009-2012, 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>
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +053036#include <linux/usb/quirks.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053037#include <linux/usb/msm_hsusb.h>
38#include <linux/usb/msm_hsusb_hw.h>
Anji jonnala11aa5c42011-05-04 10:19:48 +053039#include <linux/regulator/consumer.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040#include <linux/mfd/pm8xxx/pm8921-charger.h>
Pavankumar Kondeti446f4542012-02-01 13:57:13 +053041#include <linux/mfd/pm8xxx/misc.h>
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +053042#include <linux/pm_qos_params.h>
Amit Blay0f7edf72012-01-15 10:11:27 +020043#include <linux/power_supply.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053044
45#include <mach/clk.h>
Anji jonnala7da3f262011-12-02 17:22:14 -080046#include <mach/msm_xo.h>
Manu Gautamcd82e9d2011-12-20 14:17:28 +053047#include <mach/msm_bus.h>
Mayank Rana248698c2012-04-19 00:03:16 +053048#include <mach/rpm-regulator.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053049
50#define MSM_USB_BASE (motg->regs)
51#define DRIVER_NAME "msm_otg"
52
Chiranjeevi Velempati489a27c2012-03-29 09:47:17 +053053#define ID_TIMER_FREQ (jiffies + msecs_to_jiffies(500))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053054#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
Anji jonnala11aa5c42011-05-04 10:19:48 +053055#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
56#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
57#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
58#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
59
60#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
61#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
62#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
63#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
64
Mayank Rana248698c2012-04-19 00:03:16 +053065#define USB_PHY_VDD_DIG_VOL_NONE 0 /*uV */
Vamsi Krishna132b2762011-11-11 16:09:20 -080066#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
Anji jonnala11aa5c42011-05-04 10:19:48 +053067#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
68
Pavankumar Kondeti4960f312011-12-06 15:46:14 +053069static DECLARE_COMPLETION(pmic_vbus_init);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070070static struct msm_otg *the_msm_otg;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053071static bool debug_aca_enabled;
Manu Gautam8bdcc592012-03-06 11:26:06 +053072static bool debug_bus_voting_enabled;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070073
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +053074/* Prevent idle power collapse(pc) while operating in peripheral mode */
75static void otg_pm_qos_update_latency(struct msm_otg *dev, int vote)
76{
77 struct msm_otg_platform_data *pdata = dev->pdata;
78 u32 swfi_latency = 0;
79
80 if (!pdata || !pdata->swfi_latency)
81 return;
82
83 swfi_latency = pdata->swfi_latency + 1;
84
85 if (vote)
86 pm_qos_update_request(&dev->pm_qos_req_dma,
87 swfi_latency);
88 else
89 pm_qos_update_request(&dev->pm_qos_req_dma,
90 PM_QOS_DEFAULT_VALUE);
91}
92
Anji jonnala11aa5c42011-05-04 10:19:48 +053093static struct regulator *hsusb_3p3;
94static struct regulator *hsusb_1p8;
95static struct regulator *hsusb_vddcx;
Mayank Ranae3926882011-12-26 09:47:54 +053096static struct regulator *vbus_otg;
Mayank Rana9e9a2ac2012-03-24 04:05:28 +053097static struct regulator *mhl_analog_switch;
Anji jonnala11aa5c42011-05-04 10:19:48 +053098
Pavankumar Kondeti4960f312011-12-06 15:46:14 +053099static bool aca_id_turned_on;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530100static inline bool aca_enabled(void)
101{
102#ifdef CONFIG_USB_MSM_ACA
103 return true;
104#else
105 return debug_aca_enabled;
106#endif
107}
108
Mayank Rana248698c2012-04-19 00:03:16 +0530109enum usb_vdd_value {
110 VDD_NONE = 0,
111 VDD_MIN,
112 VDD_MAX,
113 VDD_VAL_MAX,
114};
Anji jonnala11aa5c42011-05-04 10:19:48 +0530115
Mayank Rana248698c2012-04-19 00:03:16 +0530116static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
117 { /* VDD_CX CORNER Voting */
118 [VDD_NONE] = RPM_VREG_CORNER_NONE,
119 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
120 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
121 },
122 { /* VDD_CX Voltage Voting */
123 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
124 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
125 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
126 },
127};
Anji jonnala11aa5c42011-05-04 10:19:48 +0530128
129static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
130{
131 int rc = 0;
132
133 if (init) {
Mayank Rana9e9a2ac2012-03-24 04:05:28 +0530134 hsusb_3p3 = devm_regulator_get(motg->otg.dev, "HSUSB_3p3");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530135 if (IS_ERR(hsusb_3p3)) {
136 dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
137 return PTR_ERR(hsusb_3p3);
138 }
139
140 rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
141 USB_PHY_3P3_VOL_MAX);
142 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700143 dev_err(motg->otg.dev, "unable to set voltage level for"
144 "hsusb 3p3\n");
Mayank Rana9e9a2ac2012-03-24 04:05:28 +0530145 return rc;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530146 }
Mayank Rana9e9a2ac2012-03-24 04:05:28 +0530147 hsusb_1p8 = devm_regulator_get(motg->otg.dev, "HSUSB_1p8");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530148 if (IS_ERR(hsusb_1p8)) {
149 dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
150 rc = PTR_ERR(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700151 goto put_3p3_lpm;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530152 }
153 rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
154 USB_PHY_1P8_VOL_MAX);
155 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700156 dev_err(motg->otg.dev, "unable to set voltage level for"
157 "hsusb 1p8\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530158 goto put_1p8;
159 }
160
161 return 0;
162 }
163
Anji jonnala11aa5c42011-05-04 10:19:48 +0530164put_1p8:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166put_3p3_lpm:
167 regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530168 return rc;
169}
170
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530171#ifdef CONFIG_PM_SLEEP
172#define USB_PHY_SUSP_DIG_VOL 500000
173static int msm_hsusb_config_vddcx(int high)
174{
Mayank Rana248698c2012-04-19 00:03:16 +0530175 struct msm_otg *motg = the_msm_otg;
176 enum usb_vdd_type vdd_type = motg->vdd_type;
177 int max_vol = vdd_val[vdd_type][VDD_MAX];
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530178 int min_vol;
179 int ret;
180
Mayank Rana248698c2012-04-19 00:03:16 +0530181 min_vol = vdd_val[vdd_type][!!high];
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530182 ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
183 if (ret) {
184 pr_err("%s: unable to set the voltage for regulator "
185 "HSUSB_VDDCX\n", __func__);
186 return ret;
187 }
188
189 pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
190
191 return ret;
192}
Hemant Kumar8e7bd072011-08-01 14:14:24 -0700193#else
194static int msm_hsusb_config_vddcx(int high)
195{
196 return 0;
197}
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530198#endif
199
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700200static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
Anji jonnala11aa5c42011-05-04 10:19:48 +0530201{
202 int ret = 0;
203
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530204 if (IS_ERR(hsusb_1p8)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530205 pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
206 return -ENODEV;
207 }
208
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530209 if (IS_ERR(hsusb_3p3)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530210 pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
211 return -ENODEV;
212 }
213
214 if (on) {
215 ret = regulator_set_optimum_mode(hsusb_1p8,
216 USB_PHY_1P8_HPM_LOAD);
217 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530219 "HSUSB_1p8\n", __func__);
220 return ret;
221 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222
223 ret = regulator_enable(hsusb_1p8);
224 if (ret) {
225 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 1p8\n",
226 __func__);
227 regulator_set_optimum_mode(hsusb_1p8, 0);
228 return ret;
229 }
230
Anji jonnala11aa5c42011-05-04 10:19:48 +0530231 ret = regulator_set_optimum_mode(hsusb_3p3,
232 USB_PHY_3P3_HPM_LOAD);
233 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700234 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530235 "HSUSB_3p3\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700236 regulator_set_optimum_mode(hsusb_1p8, 0);
237 regulator_disable(hsusb_1p8);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530238 return ret;
239 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700240
241 ret = regulator_enable(hsusb_3p3);
242 if (ret) {
243 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 3p3\n",
244 __func__);
245 regulator_set_optimum_mode(hsusb_3p3, 0);
246 regulator_set_optimum_mode(hsusb_1p8, 0);
247 regulator_disable(hsusb_1p8);
248 return ret;
249 }
250
Anji jonnala11aa5c42011-05-04 10:19:48 +0530251 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700252 ret = regulator_disable(hsusb_1p8);
253 if (ret) {
254 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 1p8\n",
255 __func__);
256 return ret;
257 }
258
259 ret = regulator_set_optimum_mode(hsusb_1p8, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530260 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700261 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530262 "HSUSB_1p8\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263
264 ret = regulator_disable(hsusb_3p3);
265 if (ret) {
266 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 3p3\n",
267 __func__);
268 return ret;
269 }
270 ret = regulator_set_optimum_mode(hsusb_3p3, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530271 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530273 "HSUSB_3p3\n", __func__);
274 }
275
276 pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
277 return ret < 0 ? ret : 0;
278}
279
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530280static void msm_hsusb_mhl_switch_enable(struct msm_otg *motg, bool on)
281{
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530282 struct msm_otg_platform_data *pdata = motg->pdata;
283
284 if (!pdata->mhl_enable)
285 return;
286
Mayank Rana9e9a2ac2012-03-24 04:05:28 +0530287 if (!mhl_analog_switch) {
288 pr_err("%s: mhl_analog_switch is NULL.\n", __func__);
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530289 return;
290 }
291
Mayank Rana9e9a2ac2012-03-24 04:05:28 +0530292 if (on) {
293 if (regulator_enable(mhl_analog_switch))
294 pr_err("unable to enable mhl_analog_switch\n");
295 } else {
296 regulator_disable(mhl_analog_switch);
297 }
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530298}
299
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530300static int ulpi_read(struct otg_transceiver *otg, u32 reg)
301{
302 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
303 int cnt = 0;
304
305 /* initiate read operation */
306 writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
307 USB_ULPI_VIEWPORT);
308
309 /* wait for completion */
310 while (cnt < ULPI_IO_TIMEOUT_USEC) {
311 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
312 break;
313 udelay(1);
314 cnt++;
315 }
316
317 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
318 dev_err(otg->dev, "ulpi_read: timeout %08x\n",
319 readl(USB_ULPI_VIEWPORT));
320 return -ETIMEDOUT;
321 }
322 return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
323}
324
325static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
326{
327 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
328 int cnt = 0;
329
330 /* initiate write operation */
331 writel(ULPI_RUN | ULPI_WRITE |
332 ULPI_ADDR(reg) | ULPI_DATA(val),
333 USB_ULPI_VIEWPORT);
334
335 /* wait for completion */
336 while (cnt < ULPI_IO_TIMEOUT_USEC) {
337 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
338 break;
339 udelay(1);
340 cnt++;
341 }
342
343 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
344 dev_err(otg->dev, "ulpi_write: timeout\n");
345 return -ETIMEDOUT;
346 }
347 return 0;
348}
349
350static struct otg_io_access_ops msm_otg_io_ops = {
351 .read = ulpi_read,
352 .write = ulpi_write,
353};
354
355static void ulpi_init(struct msm_otg *motg)
356{
357 struct msm_otg_platform_data *pdata = motg->pdata;
358 int *seq = pdata->phy_init_seq;
359
360 if (!seq)
361 return;
362
363 while (seq[0] >= 0) {
364 dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
365 seq[0], seq[1]);
366 ulpi_write(&motg->otg, seq[0], seq[1]);
367 seq += 2;
368 }
369}
370
371static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
372{
373 int ret;
374
Pavankumar Kondeti923262e2012-04-20 15:34:24 +0530375 if (IS_ERR(motg->clk))
376 return 0;
377
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530378 if (assert) {
379 ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
380 if (ret)
381 dev_err(motg->otg.dev, "usb hs_clk assert failed\n");
382 } else {
383 ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
384 if (ret)
385 dev_err(motg->otg.dev, "usb hs_clk deassert failed\n");
386 }
387 return ret;
388}
389
390static int msm_otg_phy_clk_reset(struct msm_otg *motg)
391{
392 int ret;
393
Amit Blay02eff132011-09-21 16:46:24 +0300394 if (IS_ERR(motg->phy_reset_clk))
395 return 0;
396
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530397 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
398 if (ret) {
399 dev_err(motg->otg.dev, "usb phy clk assert failed\n");
400 return ret;
401 }
402 usleep_range(10000, 12000);
403 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
404 if (ret)
405 dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
406 return ret;
407}
408
409static int msm_otg_phy_reset(struct msm_otg *motg)
410{
411 u32 val;
412 int ret;
413 int retries;
414
415 ret = msm_otg_link_clk_reset(motg, 1);
416 if (ret)
417 return ret;
418 ret = msm_otg_phy_clk_reset(motg);
419 if (ret)
420 return ret;
421 ret = msm_otg_link_clk_reset(motg, 0);
422 if (ret)
423 return ret;
424
425 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
426 writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
427
428 for (retries = 3; retries > 0; retries--) {
429 ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
430 ULPI_CLR(ULPI_FUNC_CTRL));
431 if (!ret)
432 break;
433 ret = msm_otg_phy_clk_reset(motg);
434 if (ret)
435 return ret;
436 }
437 if (!retries)
438 return -ETIMEDOUT;
439
440 /* This reset calibrates the phy, if the above write succeeded */
441 ret = msm_otg_phy_clk_reset(motg);
442 if (ret)
443 return ret;
444
445 for (retries = 3; retries > 0; retries--) {
446 ret = ulpi_read(&motg->otg, ULPI_DEBUG);
447 if (ret != -ETIMEDOUT)
448 break;
449 ret = msm_otg_phy_clk_reset(motg);
450 if (ret)
451 return ret;
452 }
453 if (!retries)
454 return -ETIMEDOUT;
455
456 dev_info(motg->otg.dev, "phy_reset: success\n");
457 return 0;
458}
459
460#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530461static int msm_otg_link_reset(struct msm_otg *motg)
462{
463 int cnt = 0;
464
465 writel_relaxed(USBCMD_RESET, USB_USBCMD);
466 while (cnt < LINK_RESET_TIMEOUT_USEC) {
467 if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
468 break;
469 udelay(1);
470 cnt++;
471 }
472 if (cnt >= LINK_RESET_TIMEOUT_USEC)
473 return -ETIMEDOUT;
474
475 /* select ULPI phy */
476 writel_relaxed(0x80000000, USB_PORTSC);
477 writel_relaxed(0x0, USB_AHBBURST);
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530478 writel_relaxed(0x08, USB_AHBMODE);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530479
480 return 0;
481}
482
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530483static int msm_otg_reset(struct otg_transceiver *otg)
484{
485 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
486 struct msm_otg_platform_data *pdata = motg->pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530487 int ret;
488 u32 val = 0;
489 u32 ulpi_val = 0;
490
Ofir Cohen4da266f2012-01-03 10:19:29 +0200491 /*
492 * USB PHY and Link reset also reset the USB BAM.
493 * Thus perform reset operation only once to avoid
494 * USB BAM reset on other cases e.g. USB cable disconnections.
495 */
496 if (pdata->disable_reset_on_disconnect) {
497 if (motg->reset_counter)
498 return 0;
499 else
500 motg->reset_counter++;
501 }
502
Pavankumar Kondeti923262e2012-04-20 15:34:24 +0530503 if (!IS_ERR(motg->clk))
504 clk_prepare_enable(motg->clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530505 ret = msm_otg_phy_reset(motg);
506 if (ret) {
507 dev_err(otg->dev, "phy_reset failed\n");
508 return ret;
509 }
510
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530511 aca_id_turned_on = false;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530512 ret = msm_otg_link_reset(motg);
513 if (ret) {
514 dev_err(otg->dev, "link reset failed\n");
515 return ret;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530516 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530517 msleep(100);
Anji jonnalaa8b8d732011-12-06 10:03:24 +0530518
519 ulpi_init(motg);
520
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700521 /* Ensure that RESET operation is completed before turning off clock */
522 mb();
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530523
Pavankumar Kondeti923262e2012-04-20 15:34:24 +0530524 if (!IS_ERR(motg->clk))
525 clk_disable_unprepare(motg->clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700526
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530527 if (pdata->otg_control == OTG_PHY_CONTROL) {
528 val = readl_relaxed(USB_OTGSC);
529 if (pdata->mode == USB_OTG) {
530 ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
531 val |= OTGSC_IDIE | OTGSC_BSVIE;
532 } else if (pdata->mode == USB_PERIPHERAL) {
533 ulpi_val = ULPI_INT_SESS_VALID;
534 val |= OTGSC_BSVIE;
535 }
536 writel_relaxed(val, USB_OTGSC);
537 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
538 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
Pavankumar Kondeti446f4542012-02-01 13:57:13 +0530539 } else if (pdata->otg_control == OTG_PMIC_CONTROL) {
Vijayavardhan Vennapusa03171c72012-04-26 14:44:48 +0530540 ulpi_write(otg, OTG_COMP_DISABLE,
541 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
Pavankumar Kondeti446f4542012-02-01 13:57:13 +0530542 /* Enable PMIC pull-up */
543 pm8xxx_usb_id_pullup(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530544 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700545
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530546 return 0;
547}
548
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +0530549static const char *timer_string(int bit)
550{
551 switch (bit) {
552 case A_WAIT_VRISE: return "a_wait_vrise";
553 case A_WAIT_VFALL: return "a_wait_vfall";
554 case B_SRP_FAIL: return "b_srp_fail";
555 case A_WAIT_BCON: return "a_wait_bcon";
556 case A_AIDL_BDIS: return "a_aidl_bdis";
557 case A_BIDL_ADIS: return "a_bidl_adis";
558 case B_ASE0_BRST: return "b_ase0_brst";
559 case A_TST_MAINT: return "a_tst_maint";
560 case B_TST_SRP: return "b_tst_srp";
561 case B_TST_CONFIG: return "b_tst_config";
562 default: return "UNDEFINED";
563 }
564}
565
566static enum hrtimer_restart msm_otg_timer_func(struct hrtimer *hrtimer)
567{
568 struct msm_otg *motg = container_of(hrtimer, struct msm_otg, timer);
569
570 switch (motg->active_tmout) {
571 case A_WAIT_VRISE:
572 /* TODO: use vbus_vld interrupt */
573 set_bit(A_VBUS_VLD, &motg->inputs);
574 break;
575 case A_TST_MAINT:
576 /* OTG PET: End session after TA_TST_MAINT */
577 set_bit(A_BUS_DROP, &motg->inputs);
578 break;
579 case B_TST_SRP:
580 /*
581 * OTG PET: Initiate SRP after TB_TST_SRP of
582 * previous session end.
583 */
584 set_bit(B_BUS_REQ, &motg->inputs);
585 break;
586 case B_TST_CONFIG:
587 clear_bit(A_CONN, &motg->inputs);
588 break;
589 default:
590 set_bit(motg->active_tmout, &motg->tmouts);
591 }
592
593 pr_debug("expired %s timer\n", timer_string(motg->active_tmout));
594 queue_work(system_nrt_wq, &motg->sm_work);
595 return HRTIMER_NORESTART;
596}
597
598static void msm_otg_del_timer(struct msm_otg *motg)
599{
600 int bit = motg->active_tmout;
601
602 pr_debug("deleting %s timer. remaining %lld msec\n", timer_string(bit),
603 div_s64(ktime_to_us(hrtimer_get_remaining(
604 &motg->timer)), 1000));
605 hrtimer_cancel(&motg->timer);
606 clear_bit(bit, &motg->tmouts);
607}
608
609static void msm_otg_start_timer(struct msm_otg *motg, int time, int bit)
610{
611 clear_bit(bit, &motg->tmouts);
612 motg->active_tmout = bit;
613 pr_debug("starting %s timer\n", timer_string(bit));
614 hrtimer_start(&motg->timer,
615 ktime_set(time / 1000, (time % 1000) * 1000000),
616 HRTIMER_MODE_REL);
617}
618
619static void msm_otg_init_timer(struct msm_otg *motg)
620{
621 hrtimer_init(&motg->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
622 motg->timer.function = msm_otg_timer_func;
623}
624
625static int msm_otg_start_hnp(struct otg_transceiver *otg)
626{
627 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
628
629 if (otg->state != OTG_STATE_A_HOST) {
630 pr_err("HNP can not be initiated in %s state\n",
631 otg_state_string(otg->state));
632 return -EINVAL;
633 }
634
635 pr_debug("A-Host: HNP initiated\n");
636 clear_bit(A_BUS_REQ, &motg->inputs);
637 queue_work(system_nrt_wq, &motg->sm_work);
638 return 0;
639}
640
641static int msm_otg_start_srp(struct otg_transceiver *otg)
642{
643 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
644 u32 val;
645 int ret = 0;
646
647 if (otg->state != OTG_STATE_B_IDLE) {
648 pr_err("SRP can not be initiated in %s state\n",
649 otg_state_string(otg->state));
650 ret = -EINVAL;
651 goto out;
652 }
653
654 if ((jiffies - motg->b_last_se0_sess) < msecs_to_jiffies(TB_SRP_INIT)) {
655 pr_debug("initial conditions of SRP are not met. Try again"
656 "after some time\n");
657 ret = -EAGAIN;
658 goto out;
659 }
660
661 pr_debug("B-Device SRP started\n");
662
663 /*
664 * PHY won't pull D+ high unless it detects Vbus valid.
665 * Since by definition, SRP is only done when Vbus is not valid,
666 * software work-around needs to be used to spoof the PHY into
667 * thinking it is valid. This can be done using the VBUSVLDEXTSEL and
668 * VBUSVLDEXT register bits.
669 */
670 ulpi_write(otg, 0x03, 0x97);
671 /*
672 * Harware auto assist data pulsing: Data pulse is given
673 * for 7msec; wait for vbus
674 */
675 val = readl_relaxed(USB_OTGSC);
676 writel_relaxed((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, USB_OTGSC);
677
678 /* VBUS plusing is obsoleted in OTG 2.0 supplement */
679out:
680 return ret;
681}
682
683static void msm_otg_host_hnp_enable(struct otg_transceiver *otg, bool enable)
684{
685 struct usb_hcd *hcd = bus_to_hcd(otg->host);
686 struct usb_device *rhub = otg->host->root_hub;
687
688 if (enable) {
689 pm_runtime_disable(&rhub->dev);
690 rhub->state = USB_STATE_NOTATTACHED;
691 hcd->driver->bus_suspend(hcd);
692 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
693 } else {
694 usb_remove_hcd(hcd);
695 msm_otg_reset(otg);
696 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
697 }
698}
699
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530700static int msm_otg_set_suspend(struct otg_transceiver *otg, int suspend)
701{
702 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
703
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +0530704 if (aca_enabled() || (test_bit(ID, &motg->inputs) &&
705 !test_bit(ID_A, &motg->inputs)))
706 return 0;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530707
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +0530708 if (suspend) {
709 switch (otg->state) {
710 case OTG_STATE_A_WAIT_BCON:
711 if (TA_WAIT_BCON > 0)
712 break;
713 /* fall through */
714 case OTG_STATE_A_HOST:
715 pr_debug("host bus suspend\n");
716 clear_bit(A_BUS_REQ, &motg->inputs);
717 queue_work(system_nrt_wq, &motg->sm_work);
718 break;
719 default:
720 break;
721 }
722 } else {
723 switch (otg->state) {
724 case OTG_STATE_A_SUSPEND:
725 /* Remote wakeup or resume */
726 set_bit(A_BUS_REQ, &motg->inputs);
727 otg->state = OTG_STATE_A_HOST;
728 break;
729 default:
730 break;
731 }
732 }
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530733 return 0;
734}
735
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530736#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530737#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
738
739#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530740static int msm_otg_suspend(struct msm_otg *motg)
741{
742 struct otg_transceiver *otg = &motg->otg;
743 struct usb_bus *bus = otg->host;
744 struct msm_otg_platform_data *pdata = motg->pdata;
745 int cnt = 0;
Pavankumar Kondeti283146f2012-01-12 12:51:19 +0530746 bool host_bus_suspend, dcp;
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530747 u32 phy_ctrl_val = 0, cmd_val;
Stephen Boyd30ad10b2012-03-01 14:51:04 -0800748 unsigned ret;
Rajkumar Raghupathy242565d2011-12-13 12:10:59 +0530749 u32 portsc;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530750
751 if (atomic_read(&motg->in_lpm))
752 return 0;
753
754 disable_irq(motg->irq);
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530755 host_bus_suspend = otg->host && !test_bit(ID, &motg->inputs);
Pavankumar Kondeti283146f2012-01-12 12:51:19 +0530756 dcp = motg->chg_type == USB_DCP_CHARGER;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530757 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530758 * Chipidea 45-nm PHY suspend sequence:
759 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530760 * Interrupt Latch Register auto-clear feature is not present
761 * in all PHY versions. Latch register is clear on read type.
762 * Clear latch register to avoid spurious wakeup from
763 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530764 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530765 * PHY comparators are disabled when PHY enters into low power
766 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
767 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
768 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530769 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530770 * PLL is not turned off when PHY enters into low power mode (LPM).
771 * Disable PLL for maximum power savings.
772 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530773
774 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
775 ulpi_read(otg, 0x14);
776 if (pdata->otg_control == OTG_PHY_CONTROL)
777 ulpi_write(otg, 0x01, 0x30);
778 ulpi_write(otg, 0x08, 0x09);
779 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530780
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700781
Rajkumar Raghupathy242565d2011-12-13 12:10:59 +0530782 /* Set the PHCD bit, only if it is not set by the controller.
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530783 * PHY may take some time or even fail to enter into low power
784 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
785 * in failure case.
786 */
Rajkumar Raghupathy242565d2011-12-13 12:10:59 +0530787 portsc = readl_relaxed(USB_PORTSC);
788 if (!(portsc & PORTSC_PHCD)) {
789 writel_relaxed(portsc | PORTSC_PHCD,
790 USB_PORTSC);
791 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
792 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
793 break;
794 udelay(1);
795 cnt++;
796 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530797 }
798
799 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
800 dev_err(otg->dev, "Unable to suspend PHY\n");
801 msm_otg_reset(otg);
802 enable_irq(motg->irq);
803 return -ETIMEDOUT;
804 }
805
806 /*
807 * PHY has capability to generate interrupt asynchronously in low
808 * power mode (LPM). This interrupt is level triggered. So USB IRQ
809 * line must be disabled till async interrupt enable bit is cleared
810 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
811 * block data communication from PHY.
Pavankumar Kondeti6be675f2012-04-16 13:29:24 +0530812 *
813 * PHY retention mode is disallowed while entering to LPM with wall
814 * charger connected. But PHY is put into suspend mode. Hence
815 * enable asynchronous interrupt to detect charger disconnection when
816 * PMIC notifications are unavailable.
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530817 */
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530818 cmd_val = readl_relaxed(USB_USBCMD);
Pavankumar Kondeti6be675f2012-04-16 13:29:24 +0530819 if (host_bus_suspend || (motg->pdata->otg_control == OTG_PHY_CONTROL &&
820 dcp))
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530821 cmd_val |= ASYNC_INTR_CTRL | ULPI_STP_CTRL;
822 else
823 cmd_val |= ULPI_STP_CTRL;
824 writel_relaxed(cmd_val, USB_USBCMD);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530825
Pavankumar Kondeti283146f2012-01-12 12:51:19 +0530826 /*
827 * BC1.2 spec mandates PD to enable VDP_SRC when charging from DCP.
828 * PHY retention and collapse can not happen with VDP_SRC enabled.
829 */
830 if (motg->caps & ALLOW_PHY_RETENTION && !host_bus_suspend && !dcp) {
Amit Blay58b31472011-11-18 09:39:39 +0200831 phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
832 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
833 /* Enable PHY HV interrupts to wake MPM/Link */
834 phy_ctrl_val |=
835 (PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
836
837 writel_relaxed(phy_ctrl_val & ~PHY_RETEN, USB_PHY_CTRL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700838 motg->lpm_flags |= PHY_RETENTIONED;
839 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530840
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841 /* Ensure that above operation is completed before turning off clocks */
842 mb();
Manu Gautam28b1bac2012-01-30 16:43:06 +0530843 clk_disable_unprepare(motg->pclk);
844 clk_disable_unprepare(motg->core_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +0530845
Anji jonnala7da3f262011-12-02 17:22:14 -0800846 /* usb phy no more require TCXO clock, hence vote for TCXO disable */
Stephen Boyd30ad10b2012-03-01 14:51:04 -0800847 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
848 if (ret)
849 dev_err(otg->dev, "%s failed to devote for "
850 "TCXO D0 buffer%d\n", __func__, ret);
Anji jonnala7da3f262011-12-02 17:22:14 -0800851
Pavankumar Kondeti283146f2012-01-12 12:51:19 +0530852 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE &&
853 !host_bus_suspend && !dcp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700854 msm_hsusb_ldo_enable(motg, 0);
855 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530856 }
857
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530858 if (motg->lpm_flags & PHY_RETENTIONED) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700859 msm_hsusb_config_vddcx(0);
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530860 msm_hsusb_mhl_switch_enable(motg, 0);
861 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700862
863 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530864 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700865 if (motg->pdata->pmic_id_irq)
866 enable_irq_wake(motg->pdata->pmic_id_irq);
867 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530868 if (bus)
869 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
870
871 atomic_set(&motg->in_lpm, 1);
872 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700873 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530874
875 dev_info(otg->dev, "USB in low power mode\n");
876
877 return 0;
878}
879
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530880static int msm_otg_resume(struct msm_otg *motg)
881{
882 struct otg_transceiver *otg = &motg->otg;
883 struct usb_bus *bus = otg->host;
884 int cnt = 0;
885 unsigned temp;
Amit Blay58b31472011-11-18 09:39:39 +0200886 u32 phy_ctrl_val = 0;
Anji jonnala7da3f262011-12-02 17:22:14 -0800887 unsigned ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530888
889 if (!atomic_read(&motg->in_lpm))
890 return 0;
891
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700892 wake_lock(&motg->wlock);
Anji jonnala7da3f262011-12-02 17:22:14 -0800893
894 /* Vote for TCXO when waking up the phy */
Stephen Boyd30ad10b2012-03-01 14:51:04 -0800895 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
Anji jonnala7da3f262011-12-02 17:22:14 -0800896 if (ret)
897 dev_err(otg->dev, "%s failed to vote for "
898 "TCXO D0 buffer%d\n", __func__, ret);
899
Manu Gautam28b1bac2012-01-30 16:43:06 +0530900 clk_prepare_enable(motg->core_clk);
Amit Blay137575f2011-11-06 15:20:54 +0200901
Manu Gautam28b1bac2012-01-30 16:43:06 +0530902 clk_prepare_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530903
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
905 msm_hsusb_ldo_enable(motg, 1);
906 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
907 }
908
909 if (motg->lpm_flags & PHY_RETENTIONED) {
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530910 msm_hsusb_mhl_switch_enable(motg, 1);
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530911 msm_hsusb_config_vddcx(1);
Amit Blay58b31472011-11-18 09:39:39 +0200912 phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
913 phy_ctrl_val |= PHY_RETEN;
914 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
915 /* Disable PHY HV interrupts */
916 phy_ctrl_val &=
917 ~(PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
918 writel_relaxed(phy_ctrl_val, USB_PHY_CTRL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700919 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530920 }
921
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530922 temp = readl(USB_USBCMD);
923 temp &= ~ASYNC_INTR_CTRL;
924 temp &= ~ULPI_STP_CTRL;
925 writel(temp, USB_USBCMD);
926
927 /*
928 * PHY comes out of low power mode (LPM) in case of wakeup
929 * from asynchronous interrupt.
930 */
931 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
932 goto skip_phy_resume;
933
934 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
935 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
936 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
937 break;
938 udelay(1);
939 cnt++;
940 }
941
942 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
943 /*
944 * This is a fatal error. Reset the link and
945 * PHY. USB state can not be restored. Re-insertion
946 * of USB cable is the only way to get USB working.
947 */
948 dev_err(otg->dev, "Unable to resume USB."
949 "Re-plugin the cable\n");
950 msm_otg_reset(otg);
951 }
952
953skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700954 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530955 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700956 if (motg->pdata->pmic_id_irq)
957 disable_irq_wake(motg->pdata->pmic_id_irq);
958 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530959 if (bus)
960 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
961
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530962 atomic_set(&motg->in_lpm, 0);
963
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530964 if (motg->async_int) {
965 motg->async_int = 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530966 enable_irq(motg->irq);
967 }
968
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530969 dev_info(otg->dev, "USB exited from low power mode\n");
970
971 return 0;
972}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530973#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530974
David Keitel081a3e22012-04-18 12:37:07 -0700975static int msm_otg_notify_chg_type(struct msm_otg *motg)
976{
977 static int charger_type;
978 /*
979 * TODO
980 * Unify OTG driver charger types and power supply charger types
981 */
982 if (charger_type == motg->chg_type)
983 return 0;
984
985 if (motg->chg_type == USB_SDP_CHARGER)
986 charger_type = POWER_SUPPLY_TYPE_USB;
987 else if (motg->chg_type == USB_CDP_CHARGER)
988 charger_type = POWER_SUPPLY_TYPE_USB_CDP;
989 else if (motg->chg_type == USB_DCP_CHARGER)
990 charger_type = POWER_SUPPLY_TYPE_USB_DCP;
991 else if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
992 motg->chg_type == USB_ACA_A_CHARGER ||
993 motg->chg_type == USB_ACA_B_CHARGER ||
994 motg->chg_type == USB_ACA_C_CHARGER))
995 charger_type = POWER_SUPPLY_TYPE_USB_ACA;
996 else
997 charger_type = POWER_SUPPLY_TYPE_BATTERY;
998
999 return pm8921_set_usb_power_supply_type(charger_type);
1000}
1001
Amit Blay0f7edf72012-01-15 10:11:27 +02001002static int msm_otg_notify_power_supply(struct msm_otg *motg, unsigned mA)
1003{
1004 struct power_supply *psy;
1005
1006 psy = power_supply_get_by_name("usb");
1007 if (!psy)
1008 goto psy_not_supported;
1009
1010 if (motg->cur_power == 0 && mA > 0) {
1011 /* Enable charging */
1012 if (power_supply_set_online(psy, true))
1013 goto psy_not_supported;
1014 } else if (motg->cur_power > 0 && mA == 0) {
1015 /* Disable charging */
1016 if (power_supply_set_online(psy, false))
1017 goto psy_not_supported;
1018 return 0;
1019 }
1020 /* Set max current limit */
1021 if (power_supply_set_current_limit(psy, 1000*mA))
1022 goto psy_not_supported;
1023
1024 return 0;
1025
1026psy_not_supported:
1027 dev_dbg(motg->otg.dev, "Power Supply doesn't support USB charger\n");
1028 return -ENXIO;
1029}
1030
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301031static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
1032{
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301033 struct usb_gadget *g = motg->otg.gadget;
1034
1035 if (g && g->is_a_peripheral)
1036 return;
1037
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301038 if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
1039 motg->chg_type == USB_ACA_A_CHARGER ||
1040 motg->chg_type == USB_ACA_B_CHARGER ||
1041 motg->chg_type == USB_ACA_C_CHARGER) &&
1042 mA > IDEV_ACA_CHG_LIMIT)
1043 mA = IDEV_ACA_CHG_LIMIT;
1044
David Keitel081a3e22012-04-18 12:37:07 -07001045 if (msm_otg_notify_chg_type(motg))
1046 dev_err(motg->otg.dev,
1047 "Failed notifying %d charger type to PMIC\n",
1048 motg->chg_type);
1049
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301050 if (motg->cur_power == mA)
1051 return;
1052
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301053 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Amit Blay0f7edf72012-01-15 10:11:27 +02001054
1055 /*
1056 * Use Power Supply API if supported, otherwise fallback
1057 * to legacy pm8921 API.
1058 */
1059 if (msm_otg_notify_power_supply(motg, mA))
1060 pm8921_charger_vbus_draw(mA);
1061
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301062 motg->cur_power = mA;
1063}
1064
1065static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
1066{
1067 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1068
1069 /*
1070 * Gadget driver uses set_power method to notify about the
1071 * available current based on suspend/configured states.
1072 *
1073 * IDEV_CHG can be drawn irrespective of suspend/un-configured
1074 * states when CDP/ACA is connected.
1075 */
1076 if (motg->chg_type == USB_SDP_CHARGER)
1077 msm_otg_notify_charger(motg, mA);
1078
1079 return 0;
1080}
1081
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301082static void msm_otg_start_host(struct otg_transceiver *otg, int on)
1083{
1084 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1085 struct msm_otg_platform_data *pdata = motg->pdata;
1086 struct usb_hcd *hcd;
1087
1088 if (!otg->host)
1089 return;
1090
1091 hcd = bus_to_hcd(otg->host);
1092
1093 if (on) {
1094 dev_dbg(otg->dev, "host on\n");
1095
Vijayavardhan Vennapusa03171c72012-04-26 14:44:48 +05301096 if (pdata->otg_control == OTG_PHY_CONTROL)
1097 ulpi_write(otg, OTG_COMP_DISABLE,
1098 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
1099
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301100 /*
1101 * Some boards have a switch cotrolled by gpio
1102 * to enable/disable internal HUB. Enable internal
1103 * HUB before kicking the host.
1104 */
1105 if (pdata->setup_gpio)
1106 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301107 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301108 } else {
1109 dev_dbg(otg->dev, "host off\n");
1110
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301111 usb_remove_hcd(hcd);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301112 /* HCD core reset all bits of PORTSC. select ULPI phy */
1113 writel_relaxed(0x80000000, USB_PORTSC);
1114
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301115 if (pdata->setup_gpio)
1116 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Vijayavardhan Vennapusa03171c72012-04-26 14:44:48 +05301117
1118 if (pdata->otg_control == OTG_PHY_CONTROL)
1119 ulpi_write(otg, OTG_COMP_DISABLE,
1120 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301121 }
1122}
1123
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001124static int msm_otg_usbdev_notify(struct notifier_block *self,
1125 unsigned long action, void *priv)
1126{
1127 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301128 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301129 struct usb_device *udev = priv;
1130
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301131 if (action == USB_BUS_ADD || action == USB_BUS_REMOVE)
1132 goto out;
1133
1134 if (udev->bus != motg->otg.host)
1135 goto out;
1136 /*
1137 * Interested in devices connected directly to the root hub.
1138 * ACA dock can supply IDEV_CHG irrespective devices connected
1139 * on the accessory port.
1140 */
1141 if (!udev->parent || udev->parent->parent ||
1142 motg->chg_type == USB_ACA_DOCK_CHARGER)
1143 goto out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001144
1145 switch (action) {
1146 case USB_DEVICE_ADD:
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301147 if (aca_enabled())
1148 usb_disable_autosuspend(udev);
1149 if (otg->state == OTG_STATE_A_WAIT_BCON) {
1150 pr_debug("B_CONN set\n");
1151 set_bit(B_CONN, &motg->inputs);
1152 msm_otg_del_timer(motg);
1153 otg->state = OTG_STATE_A_HOST;
1154 /*
1155 * OTG PET: A-device must end session within
1156 * 10 sec after PET enumeration.
1157 */
1158 if (udev->quirks & USB_QUIRK_OTG_PET)
1159 msm_otg_start_timer(motg, TA_TST_MAINT,
1160 A_TST_MAINT);
1161 }
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301162 /* fall through */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001163 case USB_DEVICE_CONFIG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001164 if (udev->actconfig)
1165 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
1166 else
1167 motg->mA_port = IUNIT;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301168 if (otg->state == OTG_STATE_B_HOST)
1169 msm_otg_del_timer(motg);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301170 break;
1171 case USB_DEVICE_REMOVE:
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301172 if ((otg->state == OTG_STATE_A_HOST) ||
1173 (otg->state == OTG_STATE_A_SUSPEND)) {
1174 pr_debug("B_CONN clear\n");
1175 clear_bit(B_CONN, &motg->inputs);
1176 /*
1177 * OTG PET: A-device must end session after
1178 * PET disconnection if it is enumerated
1179 * with bcdDevice[0] = 1. USB core sets
1180 * bus->otg_vbus_off for us. clear it here.
1181 */
1182 if (udev->bus->otg_vbus_off) {
1183 udev->bus->otg_vbus_off = 0;
1184 set_bit(A_BUS_DROP, &motg->inputs);
1185 }
1186 queue_work(system_nrt_wq, &motg->sm_work);
1187 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001188 default:
1189 break;
1190 }
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301191 if (test_bit(ID_A, &motg->inputs))
1192 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX -
1193 motg->mA_port);
1194out:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001195 return NOTIFY_OK;
1196}
1197
Mayank Ranae3926882011-12-26 09:47:54 +05301198static void msm_hsusb_vbus_power(struct msm_otg *motg, bool on)
1199{
1200 int ret;
1201 static bool vbus_is_on;
1202
1203 if (vbus_is_on == on)
1204 return;
1205
1206 if (motg->pdata->vbus_power) {
Mayank Rana91f597e2012-01-20 10:12:06 +05301207 ret = motg->pdata->vbus_power(on);
1208 if (!ret)
1209 vbus_is_on = on;
Mayank Ranae3926882011-12-26 09:47:54 +05301210 return;
1211 }
1212
1213 if (!vbus_otg) {
1214 pr_err("vbus_otg is NULL.");
1215 return;
1216 }
1217
Abhijeet Dharmapurikarbe054882012-01-03 20:27:07 -08001218 /*
1219 * if entering host mode tell the charger to not draw any current
1220 * from usb - if exiting host mode let the charger draw current
1221 */
1222 pm8921_disable_source_current(on);
Mayank Ranae3926882011-12-26 09:47:54 +05301223 if (on) {
1224 ret = regulator_enable(vbus_otg);
1225 if (ret) {
1226 pr_err("unable to enable vbus_otg\n");
1227 return;
1228 }
1229 vbus_is_on = true;
1230 } else {
1231 ret = regulator_disable(vbus_otg);
1232 if (ret) {
1233 pr_err("unable to disable vbus_otg\n");
1234 return;
1235 }
1236 vbus_is_on = false;
1237 }
1238}
1239
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301240static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
1241{
1242 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1243 struct usb_hcd *hcd;
1244
1245 /*
1246 * Fail host registration if this board can support
1247 * only peripheral configuration.
1248 */
1249 if (motg->pdata->mode == USB_PERIPHERAL) {
1250 dev_info(otg->dev, "Host mode is not supported\n");
1251 return -ENODEV;
1252 }
1253
Mayank Ranae3926882011-12-26 09:47:54 +05301254 if (!motg->pdata->vbus_power && host) {
Mayank Rana9e9a2ac2012-03-24 04:05:28 +05301255 vbus_otg = devm_regulator_get(motg->otg.dev, "vbus_otg");
Mayank Ranae3926882011-12-26 09:47:54 +05301256 if (IS_ERR(vbus_otg)) {
1257 pr_err("Unable to get vbus_otg\n");
1258 return -ENODEV;
1259 }
1260 }
1261
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301262 if (!host) {
1263 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301264 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001265 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301266 msm_otg_start_host(otg, 0);
Mayank Ranae3926882011-12-26 09:47:54 +05301267 msm_hsusb_vbus_power(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301268 otg->host = NULL;
1269 otg->state = OTG_STATE_UNDEFINED;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301270 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301271 } else {
1272 otg->host = NULL;
1273 }
1274
1275 return 0;
1276 }
1277
1278 hcd = bus_to_hcd(host);
1279 hcd->power_budget = motg->pdata->power_budget;
1280
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301281#ifdef CONFIG_USB_OTG
1282 host->otg_port = 1;
1283#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001284 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
1285 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301286 otg->host = host;
1287 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
1288
1289 /*
1290 * Kick the state machine work, if peripheral is not supported
1291 * or peripheral is already registered with us.
1292 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301293 if (motg->pdata->mode == USB_HOST || otg->gadget) {
1294 pm_runtime_get_sync(otg->dev);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301295 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301296 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301297
1298 return 0;
1299}
1300
1301static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
1302{
Manu Gautamcd82e9d2011-12-20 14:17:28 +05301303 int ret;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301304 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1305 struct msm_otg_platform_data *pdata = motg->pdata;
1306
1307 if (!otg->gadget)
1308 return;
1309
1310 if (on) {
1311 dev_dbg(otg->dev, "gadget on\n");
1312 /*
1313 * Some boards have a switch cotrolled by gpio
1314 * to enable/disable internal HUB. Disable internal
1315 * HUB before kicking the gadget.
1316 */
1317 if (pdata->setup_gpio)
1318 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05301319 /*
1320 * vote for minimum dma_latency to prevent idle
1321 * power collapse(pc) while running in peripheral mode.
1322 */
1323 otg_pm_qos_update_latency(motg, 1);
Manu Gautamcd82e9d2011-12-20 14:17:28 +05301324 /* Configure BUS performance parameters for MAX bandwidth */
Manu Gautam8bdcc592012-03-06 11:26:06 +05301325 if (motg->bus_perf_client && debug_bus_voting_enabled) {
Manu Gautamcd82e9d2011-12-20 14:17:28 +05301326 ret = msm_bus_scale_client_update_request(
1327 motg->bus_perf_client, 1);
1328 if (ret)
1329 dev_err(motg->otg.dev, "%s: Failed to vote for "
1330 "bus bandwidth %d\n", __func__, ret);
1331 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301332 usb_gadget_vbus_connect(otg->gadget);
1333 } else {
1334 dev_dbg(otg->dev, "gadget off\n");
1335 usb_gadget_vbus_disconnect(otg->gadget);
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05301336 otg_pm_qos_update_latency(motg, 0);
Manu Gautamcd82e9d2011-12-20 14:17:28 +05301337 /* Configure BUS performance parameters to default */
1338 if (motg->bus_perf_client) {
1339 ret = msm_bus_scale_client_update_request(
1340 motg->bus_perf_client, 0);
1341 if (ret)
1342 dev_err(motg->otg.dev, "%s: Failed to devote "
1343 "for bus bw %d\n", __func__, ret);
1344 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301345 if (pdata->setup_gpio)
1346 pdata->setup_gpio(OTG_STATE_UNDEFINED);
1347 }
1348
1349}
1350
1351static int msm_otg_set_peripheral(struct otg_transceiver *otg,
1352 struct usb_gadget *gadget)
1353{
1354 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1355
1356 /*
1357 * Fail peripheral registration if this board can support
1358 * only host configuration.
1359 */
1360 if (motg->pdata->mode == USB_HOST) {
1361 dev_info(otg->dev, "Peripheral mode is not supported\n");
1362 return -ENODEV;
1363 }
1364
1365 if (!gadget) {
1366 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301367 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301368 msm_otg_start_peripheral(otg, 0);
1369 otg->gadget = NULL;
1370 otg->state = OTG_STATE_UNDEFINED;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301371 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301372 } else {
1373 otg->gadget = NULL;
1374 }
1375
1376 return 0;
1377 }
1378 otg->gadget = gadget;
1379 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
1380
1381 /*
1382 * Kick the state machine work, if host is not supported
1383 * or host is already registered with us.
1384 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301385 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
1386 pm_runtime_get_sync(otg->dev);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301387 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301388 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301389
1390 return 0;
1391}
1392
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001393static bool msm_chg_aca_detect(struct msm_otg *motg)
1394{
1395 struct otg_transceiver *otg = &motg->otg;
1396 u32 int_sts;
1397 bool ret = false;
1398
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301399 if (!aca_enabled())
1400 goto out;
1401
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001402 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
1403 goto out;
1404
1405 int_sts = ulpi_read(otg, 0x87);
1406 switch (int_sts & 0x1C) {
1407 case 0x08:
1408 if (!test_and_set_bit(ID_A, &motg->inputs)) {
1409 dev_dbg(otg->dev, "ID_A\n");
1410 motg->chg_type = USB_ACA_A_CHARGER;
1411 motg->chg_state = USB_CHG_STATE_DETECTED;
1412 clear_bit(ID_B, &motg->inputs);
1413 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301414 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001415 ret = true;
1416 }
1417 break;
1418 case 0x0C:
1419 if (!test_and_set_bit(ID_B, &motg->inputs)) {
1420 dev_dbg(otg->dev, "ID_B\n");
1421 motg->chg_type = USB_ACA_B_CHARGER;
1422 motg->chg_state = USB_CHG_STATE_DETECTED;
1423 clear_bit(ID_A, &motg->inputs);
1424 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301425 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001426 ret = true;
1427 }
1428 break;
1429 case 0x10:
1430 if (!test_and_set_bit(ID_C, &motg->inputs)) {
1431 dev_dbg(otg->dev, "ID_C\n");
1432 motg->chg_type = USB_ACA_C_CHARGER;
1433 motg->chg_state = USB_CHG_STATE_DETECTED;
1434 clear_bit(ID_A, &motg->inputs);
1435 clear_bit(ID_B, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301436 set_bit(ID, &motg->inputs);
1437 ret = true;
1438 }
1439 break;
1440 case 0x04:
1441 if (test_and_clear_bit(ID, &motg->inputs)) {
1442 dev_dbg(otg->dev, "ID_GND\n");
1443 motg->chg_type = USB_INVALID_CHARGER;
1444 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1445 clear_bit(ID_A, &motg->inputs);
1446 clear_bit(ID_B, &motg->inputs);
1447 clear_bit(ID_C, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001448 ret = true;
1449 }
1450 break;
1451 default:
1452 ret = test_and_clear_bit(ID_A, &motg->inputs) |
1453 test_and_clear_bit(ID_B, &motg->inputs) |
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301454 test_and_clear_bit(ID_C, &motg->inputs) |
1455 !test_and_set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001456 if (ret) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301457 dev_dbg(otg->dev, "ID A/B/C/GND is no more\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001458 motg->chg_type = USB_INVALID_CHARGER;
1459 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1460 }
1461 }
1462out:
1463 return ret;
1464}
1465
1466static void msm_chg_enable_aca_det(struct msm_otg *motg)
1467{
1468 struct otg_transceiver *otg = &motg->otg;
1469
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301470 if (!aca_enabled())
1471 return;
1472
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001473 switch (motg->pdata->phy_type) {
1474 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301475 /* Disable ID_GND in link and PHY */
1476 writel_relaxed(readl_relaxed(USB_OTGSC) & ~(OTGSC_IDPU |
1477 OTGSC_IDIE), USB_OTGSC);
1478 ulpi_write(otg, 0x01, 0x0C);
1479 ulpi_write(otg, 0x10, 0x0F);
1480 ulpi_write(otg, 0x10, 0x12);
Pavankumar Kondeti446f4542012-02-01 13:57:13 +05301481 /* Disable PMIC ID pull-up */
1482 pm8xxx_usb_id_pullup(0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301483 /* Enable ACA ID detection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001484 ulpi_write(otg, 0x20, 0x85);
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301485 aca_id_turned_on = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001486 break;
1487 default:
1488 break;
1489 }
1490}
1491
1492static void msm_chg_enable_aca_intr(struct msm_otg *motg)
1493{
1494 struct otg_transceiver *otg = &motg->otg;
1495
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301496 if (!aca_enabled())
1497 return;
1498
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001499 switch (motg->pdata->phy_type) {
1500 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301501 /* Enable ACA Detection interrupt (on any RID change) */
1502 ulpi_write(otg, 0x01, 0x94);
1503 break;
1504 default:
1505 break;
1506 }
1507}
1508
1509static void msm_chg_disable_aca_intr(struct msm_otg *motg)
1510{
1511 struct otg_transceiver *otg = &motg->otg;
1512
1513 if (!aca_enabled())
1514 return;
1515
1516 switch (motg->pdata->phy_type) {
1517 case SNPS_28NM_INTEGRATED_PHY:
1518 ulpi_write(otg, 0x01, 0x95);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001519 break;
1520 default:
1521 break;
1522 }
1523}
1524
1525static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1526{
1527 struct otg_transceiver *otg = &motg->otg;
1528 bool ret = false;
1529
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301530 if (!aca_enabled())
1531 return ret;
1532
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001533 switch (motg->pdata->phy_type) {
1534 case SNPS_28NM_INTEGRATED_PHY:
1535 if (ulpi_read(otg, 0x91) & 1) {
1536 dev_dbg(otg->dev, "RID change\n");
1537 ulpi_write(otg, 0x01, 0x92);
1538 ret = msm_chg_aca_detect(motg);
1539 }
1540 default:
1541 break;
1542 }
1543 return ret;
1544}
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301545
1546static void msm_otg_id_timer_func(unsigned long data)
1547{
1548 struct msm_otg *motg = (struct msm_otg *) data;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301549 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301550
1551 if (!aca_enabled())
1552 return;
1553
1554 if (atomic_read(&motg->in_lpm)) {
1555 dev_dbg(motg->otg.dev, "timer: in lpm\n");
1556 return;
1557 }
1558
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301559 if (otg->state == OTG_STATE_A_SUSPEND)
1560 goto out;
1561
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301562 if (msm_chg_check_aca_intr(motg)) {
1563 dev_dbg(motg->otg.dev, "timer: aca work\n");
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301564 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301565 }
1566
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301567out:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301568 if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs))
1569 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
1570}
1571
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301572static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1573{
1574 struct otg_transceiver *otg = &motg->otg;
1575 u32 chg_det;
1576 bool ret = false;
1577
1578 switch (motg->pdata->phy_type) {
1579 case CI_45NM_INTEGRATED_PHY:
1580 chg_det = ulpi_read(otg, 0x34);
1581 ret = chg_det & (1 << 4);
1582 break;
1583 case SNPS_28NM_INTEGRATED_PHY:
1584 chg_det = ulpi_read(otg, 0x87);
1585 ret = chg_det & 1;
1586 break;
1587 default:
1588 break;
1589 }
1590 return ret;
1591}
1592
1593static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1594{
1595 struct otg_transceiver *otg = &motg->otg;
1596 u32 chg_det;
1597
1598 switch (motg->pdata->phy_type) {
1599 case CI_45NM_INTEGRATED_PHY:
1600 chg_det = ulpi_read(otg, 0x34);
1601 /* Turn off charger block */
1602 chg_det |= ~(1 << 1);
1603 ulpi_write(otg, chg_det, 0x34);
1604 udelay(20);
1605 /* control chg block via ULPI */
1606 chg_det &= ~(1 << 3);
1607 ulpi_write(otg, chg_det, 0x34);
1608 /* put it in host mode for enabling D- source */
1609 chg_det &= ~(1 << 2);
1610 ulpi_write(otg, chg_det, 0x34);
1611 /* Turn on chg detect block */
1612 chg_det &= ~(1 << 1);
1613 ulpi_write(otg, chg_det, 0x34);
1614 udelay(20);
1615 /* enable chg detection */
1616 chg_det &= ~(1 << 0);
1617 ulpi_write(otg, chg_det, 0x34);
1618 break;
1619 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondeti283146f2012-01-12 12:51:19 +05301620 /* Turn off VDP_SRC */
1621 ulpi_write(otg, 0x3, 0x86);
1622 msleep(20);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301623 /*
1624 * Configure DM as current source, DP as current sink
1625 * and enable battery charging comparators.
1626 */
1627 ulpi_write(otg, 0x8, 0x85);
1628 ulpi_write(otg, 0x2, 0x85);
1629 ulpi_write(otg, 0x1, 0x85);
1630 break;
1631 default:
1632 break;
1633 }
1634}
1635
1636static bool msm_chg_check_primary_det(struct msm_otg *motg)
1637{
1638 struct otg_transceiver *otg = &motg->otg;
1639 u32 chg_det;
1640 bool ret = false;
1641
1642 switch (motg->pdata->phy_type) {
1643 case CI_45NM_INTEGRATED_PHY:
1644 chg_det = ulpi_read(otg, 0x34);
1645 ret = chg_det & (1 << 4);
1646 break;
1647 case SNPS_28NM_INTEGRATED_PHY:
1648 chg_det = ulpi_read(otg, 0x87);
1649 ret = chg_det & 1;
1650 break;
1651 default:
1652 break;
1653 }
1654 return ret;
1655}
1656
1657static void msm_chg_enable_primary_det(struct msm_otg *motg)
1658{
1659 struct otg_transceiver *otg = &motg->otg;
1660 u32 chg_det;
1661
1662 switch (motg->pdata->phy_type) {
1663 case CI_45NM_INTEGRATED_PHY:
1664 chg_det = ulpi_read(otg, 0x34);
1665 /* enable chg detection */
1666 chg_det &= ~(1 << 0);
1667 ulpi_write(otg, chg_det, 0x34);
1668 break;
1669 case SNPS_28NM_INTEGRATED_PHY:
1670 /*
1671 * Configure DP as current source, DM as current sink
1672 * and enable battery charging comparators.
1673 */
1674 ulpi_write(otg, 0x2, 0x85);
1675 ulpi_write(otg, 0x1, 0x85);
1676 break;
1677 default:
1678 break;
1679 }
1680}
1681
1682static bool msm_chg_check_dcd(struct msm_otg *motg)
1683{
1684 struct otg_transceiver *otg = &motg->otg;
1685 u32 line_state;
1686 bool ret = false;
1687
1688 switch (motg->pdata->phy_type) {
1689 case CI_45NM_INTEGRATED_PHY:
1690 line_state = ulpi_read(otg, 0x15);
1691 ret = !(line_state & 1);
1692 break;
1693 case SNPS_28NM_INTEGRATED_PHY:
1694 line_state = ulpi_read(otg, 0x87);
1695 ret = line_state & 2;
1696 break;
1697 default:
1698 break;
1699 }
1700 return ret;
1701}
1702
1703static void msm_chg_disable_dcd(struct msm_otg *motg)
1704{
1705 struct otg_transceiver *otg = &motg->otg;
1706 u32 chg_det;
1707
1708 switch (motg->pdata->phy_type) {
1709 case CI_45NM_INTEGRATED_PHY:
1710 chg_det = ulpi_read(otg, 0x34);
1711 chg_det &= ~(1 << 5);
1712 ulpi_write(otg, chg_det, 0x34);
1713 break;
1714 case SNPS_28NM_INTEGRATED_PHY:
1715 ulpi_write(otg, 0x10, 0x86);
1716 break;
1717 default:
1718 break;
1719 }
1720}
1721
1722static void msm_chg_enable_dcd(struct msm_otg *motg)
1723{
1724 struct otg_transceiver *otg = &motg->otg;
1725 u32 chg_det;
1726
1727 switch (motg->pdata->phy_type) {
1728 case CI_45NM_INTEGRATED_PHY:
1729 chg_det = ulpi_read(otg, 0x34);
1730 /* Turn on D+ current source */
1731 chg_det |= (1 << 5);
1732 ulpi_write(otg, chg_det, 0x34);
1733 break;
1734 case SNPS_28NM_INTEGRATED_PHY:
1735 /* Data contact detection enable */
1736 ulpi_write(otg, 0x10, 0x85);
1737 break;
1738 default:
1739 break;
1740 }
1741}
1742
1743static void msm_chg_block_on(struct msm_otg *motg)
1744{
1745 struct otg_transceiver *otg = &motg->otg;
1746 u32 func_ctrl, chg_det;
1747
1748 /* put the controller in non-driving mode */
1749 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1750 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1751 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1752 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1753
1754 switch (motg->pdata->phy_type) {
1755 case CI_45NM_INTEGRATED_PHY:
1756 chg_det = ulpi_read(otg, 0x34);
1757 /* control chg block via ULPI */
1758 chg_det &= ~(1 << 3);
1759 ulpi_write(otg, chg_det, 0x34);
1760 /* Turn on chg detect block */
1761 chg_det &= ~(1 << 1);
1762 ulpi_write(otg, chg_det, 0x34);
1763 udelay(20);
1764 break;
1765 case SNPS_28NM_INTEGRATED_PHY:
1766 /* Clear charger detecting control bits */
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301767 ulpi_write(otg, 0x1F, 0x86);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301768 /* Clear alt interrupt latch and enable bits */
1769 ulpi_write(otg, 0x1F, 0x92);
1770 ulpi_write(otg, 0x1F, 0x95);
1771 udelay(100);
1772 break;
1773 default:
1774 break;
1775 }
1776}
1777
1778static void msm_chg_block_off(struct msm_otg *motg)
1779{
1780 struct otg_transceiver *otg = &motg->otg;
1781 u32 func_ctrl, chg_det;
1782
1783 switch (motg->pdata->phy_type) {
1784 case CI_45NM_INTEGRATED_PHY:
1785 chg_det = ulpi_read(otg, 0x34);
1786 /* Turn off charger block */
1787 chg_det |= ~(1 << 1);
1788 ulpi_write(otg, chg_det, 0x34);
1789 break;
1790 case SNPS_28NM_INTEGRATED_PHY:
1791 /* Clear charger detecting control bits */
1792 ulpi_write(otg, 0x3F, 0x86);
1793 /* Clear alt interrupt latch and enable bits */
1794 ulpi_write(otg, 0x1F, 0x92);
1795 ulpi_write(otg, 0x1F, 0x95);
1796 break;
1797 default:
1798 break;
1799 }
1800
1801 /* put the controller in normal mode */
1802 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1803 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1804 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1805 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1806}
1807
Anji jonnalad270e2d2011-08-09 11:28:32 +05301808static const char *chg_to_string(enum usb_chg_type chg_type)
1809{
1810 switch (chg_type) {
1811 case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
1812 case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
1813 case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
1814 case USB_ACA_A_CHARGER: return "USB_ACA_A_CHARGER";
1815 case USB_ACA_B_CHARGER: return "USB_ACA_B_CHARGER";
1816 case USB_ACA_C_CHARGER: return "USB_ACA_C_CHARGER";
1817 case USB_ACA_DOCK_CHARGER: return "USB_ACA_DOCK_CHARGER";
1818 default: return "INVALID_CHARGER";
1819 }
1820}
1821
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301822#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1823#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
Pavankumar Kondeti283146f2012-01-12 12:51:19 +05301824#define MSM_CHG_PRIMARY_DET_TIME (50 * HZ/1000) /* TVDPSRC_ON */
1825#define MSM_CHG_SECONDARY_DET_TIME (50 * HZ/1000) /* TVDMSRC_ON */
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301826static void msm_chg_detect_work(struct work_struct *w)
1827{
1828 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1829 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti2d09e5f2012-01-16 08:56:57 +05301830 bool is_dcd = false, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301831 unsigned long delay;
1832
1833 dev_dbg(otg->dev, "chg detection work\n");
1834 switch (motg->chg_state) {
1835 case USB_CHG_STATE_UNDEFINED:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301836 msm_chg_block_on(motg);
Pavankumar Kondeti2d09e5f2012-01-16 08:56:57 +05301837 if (motg->pdata->enable_dcd)
1838 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001839 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301840 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1841 motg->dcd_retries = 0;
1842 delay = MSM_CHG_DCD_POLL_TIME;
1843 break;
1844 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001845 is_aca = msm_chg_aca_detect(motg);
1846 if (is_aca) {
1847 /*
1848 * ID_A can be ACA dock too. continue
1849 * primary detection after DCD.
1850 */
1851 if (test_bit(ID_A, &motg->inputs)) {
1852 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1853 } else {
1854 delay = 0;
1855 break;
1856 }
1857 }
Pavankumar Kondeti2d09e5f2012-01-16 08:56:57 +05301858 if (motg->pdata->enable_dcd)
1859 is_dcd = msm_chg_check_dcd(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301860 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1861 if (is_dcd || tmout) {
Pavankumar Kondeti2d09e5f2012-01-16 08:56:57 +05301862 if (motg->pdata->enable_dcd)
1863 msm_chg_disable_dcd(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301864 msm_chg_enable_primary_det(motg);
1865 delay = MSM_CHG_PRIMARY_DET_TIME;
1866 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1867 } else {
1868 delay = MSM_CHG_DCD_POLL_TIME;
1869 }
1870 break;
1871 case USB_CHG_STATE_DCD_DONE:
1872 vout = msm_chg_check_primary_det(motg);
1873 if (vout) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301874 if (test_bit(ID_A, &motg->inputs)) {
1875 motg->chg_type = USB_ACA_DOCK_CHARGER;
1876 motg->chg_state = USB_CHG_STATE_DETECTED;
1877 delay = 0;
1878 break;
1879 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301880 msm_chg_enable_secondary_det(motg);
1881 delay = MSM_CHG_SECONDARY_DET_TIME;
1882 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1883 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301884 if (test_bit(ID_A, &motg->inputs)) {
1885 motg->chg_type = USB_ACA_A_CHARGER;
1886 motg->chg_state = USB_CHG_STATE_DETECTED;
1887 delay = 0;
1888 break;
1889 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301890 motg->chg_type = USB_SDP_CHARGER;
1891 motg->chg_state = USB_CHG_STATE_DETECTED;
1892 delay = 0;
1893 }
1894 break;
1895 case USB_CHG_STATE_PRIMARY_DONE:
1896 vout = msm_chg_check_secondary_det(motg);
1897 if (vout)
1898 motg->chg_type = USB_DCP_CHARGER;
1899 else
1900 motg->chg_type = USB_CDP_CHARGER;
1901 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1902 /* fall through */
1903 case USB_CHG_STATE_SECONDARY_DONE:
1904 motg->chg_state = USB_CHG_STATE_DETECTED;
1905 case USB_CHG_STATE_DETECTED:
1906 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001907 msm_chg_enable_aca_det(motg);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301908 /*
1909 * Spurious interrupt is seen after enabling ACA detection
1910 * due to which charger detection fails in case of PET.
1911 * Add delay of 100 microsec to avoid that.
1912 */
1913 udelay(100);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001914 msm_chg_enable_aca_intr(motg);
Anji jonnalad270e2d2011-08-09 11:28:32 +05301915 dev_dbg(otg->dev, "chg_type = %s\n",
1916 chg_to_string(motg->chg_type));
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301917 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301918 return;
1919 default:
1920 return;
1921 }
1922
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301923 queue_delayed_work(system_nrt_wq, &motg->chg_work, delay);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301924}
1925
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301926/*
1927 * We support OTG, Peripheral only and Host only configurations. In case
1928 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1929 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1930 * enabled when switch is controlled by user and default mode is supplied
1931 * by board file, which can be changed by userspace later.
1932 */
1933static void msm_otg_init_sm(struct msm_otg *motg)
1934{
1935 struct msm_otg_platform_data *pdata = motg->pdata;
1936 u32 otgsc = readl(USB_OTGSC);
1937
1938 switch (pdata->mode) {
1939 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001940 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301941 if (pdata->default_mode == USB_HOST) {
1942 clear_bit(ID, &motg->inputs);
1943 } else if (pdata->default_mode == USB_PERIPHERAL) {
1944 set_bit(ID, &motg->inputs);
1945 set_bit(B_SESS_VLD, &motg->inputs);
1946 } else {
1947 set_bit(ID, &motg->inputs);
1948 clear_bit(B_SESS_VLD, &motg->inputs);
1949 }
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301950 } else if (pdata->otg_control == OTG_PHY_CONTROL) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301951 if (otgsc & OTGSC_ID) {
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301952 set_bit(ID, &motg->inputs);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301953 } else {
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301954 clear_bit(ID, &motg->inputs);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301955 set_bit(A_BUS_REQ, &motg->inputs);
1956 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001957 if (otgsc & OTGSC_BSV)
1958 set_bit(B_SESS_VLD, &motg->inputs);
1959 else
1960 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301961 } else if (pdata->otg_control == OTG_PMIC_CONTROL) {
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05301962 if (pdata->pmic_id_irq) {
Stephen Boyd431771e2012-04-18 20:00:23 -07001963 unsigned long flags;
1964 local_irq_save(flags);
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05301965 if (irq_read_line(pdata->pmic_id_irq))
1966 set_bit(ID, &motg->inputs);
1967 else
1968 clear_bit(ID, &motg->inputs);
Stephen Boyd431771e2012-04-18 20:00:23 -07001969 local_irq_restore(flags);
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05301970 }
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301971 /*
1972 * VBUS initial state is reported after PMIC
1973 * driver initialization. Wait for it.
1974 */
1975 wait_for_completion(&pmic_vbus_init);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301976 }
1977 break;
1978 case USB_HOST:
1979 clear_bit(ID, &motg->inputs);
1980 break;
1981 case USB_PERIPHERAL:
1982 set_bit(ID, &motg->inputs);
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05301983 if (pdata->otg_control == OTG_PHY_CONTROL) {
1984 if (otgsc & OTGSC_BSV)
1985 set_bit(B_SESS_VLD, &motg->inputs);
1986 else
1987 clear_bit(B_SESS_VLD, &motg->inputs);
1988 } else if (pdata->otg_control == OTG_PMIC_CONTROL) {
1989 /*
1990 * VBUS initial state is reported after PMIC
1991 * driver initialization. Wait for it.
1992 */
1993 wait_for_completion(&pmic_vbus_init);
1994 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301995 break;
1996 default:
1997 break;
1998 }
1999}
2000
2001static void msm_otg_sm_work(struct work_struct *w)
2002{
2003 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
2004 struct otg_transceiver *otg = &motg->otg;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302005 bool work = 0, srp_reqd;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302006
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302007 pm_runtime_resume(otg->dev);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302008 pr_debug("%s work\n", otg_state_string(otg->state));
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302009 switch (otg->state) {
2010 case OTG_STATE_UNDEFINED:
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302011 msm_otg_reset(otg);
2012 msm_otg_init_sm(motg);
2013 otg->state = OTG_STATE_B_IDLE;
Pavankumar Kondeti8a379b42011-12-12 13:07:23 +05302014 if (!test_bit(B_SESS_VLD, &motg->inputs) &&
2015 test_bit(ID, &motg->inputs)) {
2016 pm_runtime_put_noidle(otg->dev);
2017 pm_runtime_suspend(otg->dev);
2018 break;
2019 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302020 /* FALL THROUGH */
2021 case OTG_STATE_B_IDLE:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002022 if ((!test_bit(ID, &motg->inputs) ||
2023 test_bit(ID_A, &motg->inputs)) && otg->host) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302024 pr_debug("!id || id_A\n");
2025 clear_bit(B_BUS_REQ, &motg->inputs);
2026 set_bit(A_BUS_REQ, &motg->inputs);
2027 otg->state = OTG_STATE_A_IDLE;
2028 work = 1;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302029 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302030 pr_debug("b_sess_vld\n");
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302031 switch (motg->chg_state) {
2032 case USB_CHG_STATE_UNDEFINED:
2033 msm_chg_detect_work(&motg->chg_work.work);
2034 break;
2035 case USB_CHG_STATE_DETECTED:
2036 switch (motg->chg_type) {
2037 case USB_DCP_CHARGER:
Pavankumar Kondeti283146f2012-01-12 12:51:19 +05302038 /* Enable VDP_SRC */
2039 ulpi_write(otg, 0x2, 0x85);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302040 msm_otg_notify_charger(motg,
2041 IDEV_CHG_MAX);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302042 pm_runtime_put_noidle(otg->dev);
2043 pm_runtime_suspend(otg->dev);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302044 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302045 case USB_ACA_B_CHARGER:
2046 msm_otg_notify_charger(motg,
2047 IDEV_ACA_CHG_MAX);
2048 /*
2049 * (ID_B --> ID_C) PHY_ALT interrupt can
2050 * not be detected in LPM.
2051 */
2052 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302053 case USB_CDP_CHARGER:
2054 msm_otg_notify_charger(motg,
2055 IDEV_CHG_MAX);
2056 msm_otg_start_peripheral(otg, 1);
2057 otg->state = OTG_STATE_B_PERIPHERAL;
2058 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302059 case USB_ACA_C_CHARGER:
2060 msm_otg_notify_charger(motg,
2061 IDEV_ACA_CHG_MAX);
2062 msm_otg_start_peripheral(otg, 1);
2063 otg->state = OTG_STATE_B_PERIPHERAL;
2064 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302065 case USB_SDP_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302066 msm_otg_start_peripheral(otg, 1);
2067 otg->state = OTG_STATE_B_PERIPHERAL;
2068 break;
2069 default:
2070 break;
2071 }
2072 break;
2073 default:
2074 break;
2075 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302076 } else if (test_bit(B_BUS_REQ, &motg->inputs)) {
2077 pr_debug("b_sess_end && b_bus_req\n");
2078 if (msm_otg_start_srp(otg) < 0) {
2079 clear_bit(B_BUS_REQ, &motg->inputs);
2080 work = 1;
2081 break;
2082 }
2083 otg->state = OTG_STATE_B_SRP_INIT;
2084 msm_otg_start_timer(motg, TB_SRP_FAIL, B_SRP_FAIL);
2085 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302086 } else {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302087 pr_debug("chg_work cancel");
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302088 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302089 motg->chg_state = USB_CHG_STATE_UNDEFINED;
2090 motg->chg_type = USB_INVALID_CHARGER;
Rajkumar Raghupathy18fd7132012-04-20 11:28:13 +05302091 msm_otg_notify_charger(motg, 0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302092 msm_otg_reset(otg);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302093 pm_runtime_put_noidle(otg->dev);
2094 pm_runtime_suspend(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302095 }
2096 break;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302097 case OTG_STATE_B_SRP_INIT:
2098 if (!test_bit(ID, &motg->inputs) ||
2099 test_bit(ID_A, &motg->inputs) ||
2100 test_bit(ID_C, &motg->inputs) ||
2101 (test_bit(B_SESS_VLD, &motg->inputs) &&
2102 !test_bit(ID_B, &motg->inputs))) {
2103 pr_debug("!id || id_a/c || b_sess_vld+!id_b\n");
2104 msm_otg_del_timer(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002105 otg->state = OTG_STATE_B_IDLE;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302106 /*
2107 * clear VBUSVLDEXTSEL and VBUSVLDEXT register
2108 * bits after SRP initiation.
2109 */
2110 ulpi_write(otg, 0x0, 0x98);
2111 work = 1;
2112 } else if (test_bit(B_SRP_FAIL, &motg->tmouts)) {
2113 pr_debug("b_srp_fail\n");
2114 pr_info("A-device did not respond to SRP\n");
2115 clear_bit(B_BUS_REQ, &motg->inputs);
2116 clear_bit(B_SRP_FAIL, &motg->tmouts);
2117 otg_send_event(OTG_EVENT_NO_RESP_FOR_SRP);
2118 ulpi_write(otg, 0x0, 0x98);
2119 otg->state = OTG_STATE_B_IDLE;
2120 motg->b_last_se0_sess = jiffies;
2121 work = 1;
2122 }
2123 break;
2124 case OTG_STATE_B_PERIPHERAL:
2125 if (!test_bit(ID, &motg->inputs) ||
2126 test_bit(ID_A, &motg->inputs) ||
2127 test_bit(ID_B, &motg->inputs) ||
2128 !test_bit(B_SESS_VLD, &motg->inputs)) {
2129 pr_debug("!id || id_a/b || !b_sess_vld\n");
Rajkumar Raghupathy18fd7132012-04-20 11:28:13 +05302130 motg->chg_state = USB_CHG_STATE_UNDEFINED;
2131 motg->chg_type = USB_INVALID_CHARGER;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302132 msm_otg_notify_charger(motg, 0);
2133 srp_reqd = otg->gadget->otg_srp_reqd;
2134 msm_otg_start_peripheral(otg, 0);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302135 if (test_bit(ID_B, &motg->inputs))
2136 clear_bit(ID_B, &motg->inputs);
2137 clear_bit(B_BUS_REQ, &motg->inputs);
2138 otg->state = OTG_STATE_B_IDLE;
2139 motg->b_last_se0_sess = jiffies;
2140 if (srp_reqd)
2141 msm_otg_start_timer(motg,
2142 TB_TST_SRP, B_TST_SRP);
2143 else
2144 work = 1;
2145 } else if (test_bit(B_BUS_REQ, &motg->inputs) &&
2146 otg->gadget->b_hnp_enable &&
2147 test_bit(A_BUS_SUSPEND, &motg->inputs)) {
2148 pr_debug("b_bus_req && b_hnp_en && a_bus_suspend\n");
2149 msm_otg_start_timer(motg, TB_ASE0_BRST, B_ASE0_BRST);
2150 /* D+ pullup should not be disconnected within 4msec
2151 * after A device suspends the bus. Otherwise PET will
2152 * fail the compliance test.
2153 */
2154 udelay(1000);
2155 msm_otg_start_peripheral(otg, 0);
2156 otg->state = OTG_STATE_B_WAIT_ACON;
2157 /*
2158 * start HCD even before A-device enable
2159 * pull-up to meet HNP timings.
2160 */
2161 otg->host->is_b_host = 1;
2162 msm_otg_start_host(otg, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002163 } else if (test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302164 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002165 }
2166 break;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302167 case OTG_STATE_B_WAIT_ACON:
2168 if (!test_bit(ID, &motg->inputs) ||
2169 test_bit(ID_A, &motg->inputs) ||
2170 test_bit(ID_B, &motg->inputs) ||
2171 !test_bit(B_SESS_VLD, &motg->inputs)) {
2172 pr_debug("!id || id_a/b || !b_sess_vld\n");
2173 msm_otg_del_timer(motg);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302174 /*
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302175 * A-device is physically disconnected during
2176 * HNP. Remove HCD.
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302177 */
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302178 msm_otg_start_host(otg, 0);
2179 otg->host->is_b_host = 0;
2180
2181 clear_bit(B_BUS_REQ, &motg->inputs);
2182 clear_bit(A_BUS_SUSPEND, &motg->inputs);
2183 motg->b_last_se0_sess = jiffies;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302184 otg->state = OTG_STATE_B_IDLE;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302185 msm_otg_reset(otg);
2186 work = 1;
2187 } else if (test_bit(A_CONN, &motg->inputs)) {
2188 pr_debug("a_conn\n");
2189 clear_bit(A_BUS_SUSPEND, &motg->inputs);
2190 otg->state = OTG_STATE_B_HOST;
2191 /*
2192 * PET disconnects D+ pullup after reset is generated
2193 * by B device in B_HOST role which is not detected by
2194 * B device. As workaorund , start timer of 300msec
2195 * and stop timer if A device is enumerated else clear
2196 * A_CONN.
2197 */
2198 msm_otg_start_timer(motg, TB_TST_CONFIG,
2199 B_TST_CONFIG);
2200 } else if (test_bit(B_ASE0_BRST, &motg->tmouts)) {
2201 pr_debug("b_ase0_brst_tmout\n");
2202 pr_info("B HNP fail:No response from A device\n");
2203 msm_otg_start_host(otg, 0);
2204 msm_otg_reset(otg);
2205 otg->host->is_b_host = 0;
2206 clear_bit(B_ASE0_BRST, &motg->tmouts);
2207 clear_bit(A_BUS_SUSPEND, &motg->inputs);
2208 clear_bit(B_BUS_REQ, &motg->inputs);
2209 otg_send_event(OTG_EVENT_HNP_FAILED);
2210 otg->state = OTG_STATE_B_IDLE;
2211 work = 1;
2212 } else if (test_bit(ID_C, &motg->inputs)) {
2213 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
2214 }
2215 break;
2216 case OTG_STATE_B_HOST:
2217 if (!test_bit(B_BUS_REQ, &motg->inputs) ||
2218 !test_bit(A_CONN, &motg->inputs) ||
2219 !test_bit(B_SESS_VLD, &motg->inputs)) {
2220 pr_debug("!b_bus_req || !a_conn || !b_sess_vld\n");
2221 clear_bit(A_CONN, &motg->inputs);
2222 clear_bit(B_BUS_REQ, &motg->inputs);
2223 msm_otg_start_host(otg, 0);
2224 otg->host->is_b_host = 0;
2225 otg->state = OTG_STATE_B_IDLE;
2226 msm_otg_reset(otg);
2227 work = 1;
2228 } else if (test_bit(ID_C, &motg->inputs)) {
2229 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
2230 }
2231 break;
2232 case OTG_STATE_A_IDLE:
2233 otg->default_a = 1;
2234 if (test_bit(ID, &motg->inputs) &&
2235 !test_bit(ID_A, &motg->inputs)) {
2236 pr_debug("id && !id_a\n");
2237 otg->default_a = 0;
2238 clear_bit(A_BUS_DROP, &motg->inputs);
2239 otg->state = OTG_STATE_B_IDLE;
2240 del_timer_sync(&motg->id_timer);
2241 msm_otg_link_reset(motg);
2242 msm_chg_enable_aca_intr(motg);
2243 msm_otg_notify_charger(motg, 0);
2244 work = 1;
2245 } else if (!test_bit(A_BUS_DROP, &motg->inputs) &&
2246 (test_bit(A_SRP_DET, &motg->inputs) ||
2247 test_bit(A_BUS_REQ, &motg->inputs))) {
2248 pr_debug("!a_bus_drop && (a_srp_det || a_bus_req)\n");
2249
2250 clear_bit(A_SRP_DET, &motg->inputs);
2251 /* Disable SRP detection */
2252 writel_relaxed((readl_relaxed(USB_OTGSC) &
2253 ~OTGSC_INTSTS_MASK) &
2254 ~OTGSC_DPIE, USB_OTGSC);
2255
2256 otg->state = OTG_STATE_A_WAIT_VRISE;
2257 /* VBUS should not be supplied before end of SRP pulse
2258 * generated by PET, if not complaince test fail.
2259 */
2260 usleep_range(10000, 12000);
2261 /* ACA: ID_A: Stop charging untill enumeration */
2262 if (test_bit(ID_A, &motg->inputs))
2263 msm_otg_notify_charger(motg, 0);
2264 else
2265 msm_hsusb_vbus_power(motg, 1);
2266 msm_otg_start_timer(motg, TA_WAIT_VRISE, A_WAIT_VRISE);
2267 } else {
2268 pr_debug("No session requested\n");
2269 clear_bit(A_BUS_DROP, &motg->inputs);
2270 if (test_bit(ID_A, &motg->inputs)) {
2271 msm_otg_notify_charger(motg,
2272 IDEV_ACA_CHG_MAX);
2273 } else if (!test_bit(ID, &motg->inputs)) {
2274 msm_otg_notify_charger(motg, 0);
2275 /*
2276 * A-device is not providing power on VBUS.
2277 * Enable SRP detection.
2278 */
2279 writel_relaxed(0x13, USB_USBMODE);
2280 writel_relaxed((readl_relaxed(USB_OTGSC) &
2281 ~OTGSC_INTSTS_MASK) |
2282 OTGSC_DPIE, USB_OTGSC);
2283 mb();
2284 }
2285 }
2286 break;
2287 case OTG_STATE_A_WAIT_VRISE:
2288 if ((test_bit(ID, &motg->inputs) &&
2289 !test_bit(ID_A, &motg->inputs)) ||
2290 test_bit(A_BUS_DROP, &motg->inputs) ||
2291 test_bit(A_WAIT_VRISE, &motg->tmouts)) {
2292 pr_debug("id || a_bus_drop || a_wait_vrise_tmout\n");
2293 clear_bit(A_BUS_REQ, &motg->inputs);
2294 msm_otg_del_timer(motg);
2295 msm_hsusb_vbus_power(motg, 0);
2296 otg->state = OTG_STATE_A_WAIT_VFALL;
2297 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2298 } else if (test_bit(A_VBUS_VLD, &motg->inputs)) {
2299 pr_debug("a_vbus_vld\n");
2300 otg->state = OTG_STATE_A_WAIT_BCON;
2301 if (TA_WAIT_BCON > 0)
2302 msm_otg_start_timer(motg, TA_WAIT_BCON,
2303 A_WAIT_BCON);
2304 msm_otg_start_host(otg, 1);
2305 msm_chg_enable_aca_det(motg);
2306 msm_chg_disable_aca_intr(motg);
Chiranjeevi Velempati489a27c2012-03-29 09:47:17 +05302307 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302308 if (msm_chg_check_aca_intr(motg))
2309 work = 1;
2310 }
2311 break;
2312 case OTG_STATE_A_WAIT_BCON:
2313 if ((test_bit(ID, &motg->inputs) &&
2314 !test_bit(ID_A, &motg->inputs)) ||
2315 test_bit(A_BUS_DROP, &motg->inputs) ||
2316 test_bit(A_WAIT_BCON, &motg->tmouts)) {
2317 pr_debug("(id && id_a/b/c) || a_bus_drop ||"
2318 "a_wait_bcon_tmout\n");
2319 if (test_bit(A_WAIT_BCON, &motg->tmouts)) {
2320 pr_info("Device No Response\n");
2321 otg_send_event(OTG_EVENT_DEV_CONN_TMOUT);
2322 }
2323 msm_otg_del_timer(motg);
2324 clear_bit(A_BUS_REQ, &motg->inputs);
2325 clear_bit(B_CONN, &motg->inputs);
2326 msm_otg_start_host(otg, 0);
2327 /*
2328 * ACA: ID_A with NO accessory, just the A plug is
2329 * attached to ACA: Use IDCHG_MAX for charging
2330 */
2331 if (test_bit(ID_A, &motg->inputs))
2332 msm_otg_notify_charger(motg, IDEV_CHG_MIN);
2333 else
2334 msm_hsusb_vbus_power(motg, 0);
2335 otg->state = OTG_STATE_A_WAIT_VFALL;
2336 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2337 } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
2338 pr_debug("!a_vbus_vld\n");
2339 clear_bit(B_CONN, &motg->inputs);
2340 msm_otg_del_timer(motg);
2341 msm_otg_start_host(otg, 0);
2342 otg->state = OTG_STATE_A_VBUS_ERR;
2343 msm_otg_reset(otg);
2344 } else if (test_bit(ID_A, &motg->inputs)) {
2345 msm_hsusb_vbus_power(motg, 0);
2346 } else if (!test_bit(A_BUS_REQ, &motg->inputs)) {
2347 /*
2348 * If TA_WAIT_BCON is infinite, we don;t
2349 * turn off VBUS. Enter low power mode.
2350 */
2351 if (TA_WAIT_BCON < 0)
2352 pm_runtime_put_sync(otg->dev);
2353 } else if (!test_bit(ID, &motg->inputs)) {
2354 msm_hsusb_vbus_power(motg, 1);
2355 }
2356 break;
2357 case OTG_STATE_A_HOST:
2358 if ((test_bit(ID, &motg->inputs) &&
2359 !test_bit(ID_A, &motg->inputs)) ||
2360 test_bit(A_BUS_DROP, &motg->inputs)) {
2361 pr_debug("id_a/b/c || a_bus_drop\n");
2362 clear_bit(B_CONN, &motg->inputs);
2363 clear_bit(A_BUS_REQ, &motg->inputs);
2364 msm_otg_del_timer(motg);
2365 otg->state = OTG_STATE_A_WAIT_VFALL;
2366 msm_otg_start_host(otg, 0);
2367 if (!test_bit(ID_A, &motg->inputs))
2368 msm_hsusb_vbus_power(motg, 0);
2369 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2370 } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
2371 pr_debug("!a_vbus_vld\n");
2372 clear_bit(B_CONN, &motg->inputs);
2373 msm_otg_del_timer(motg);
2374 otg->state = OTG_STATE_A_VBUS_ERR;
2375 msm_otg_start_host(otg, 0);
2376 msm_otg_reset(otg);
2377 } else if (!test_bit(A_BUS_REQ, &motg->inputs)) {
2378 /*
2379 * a_bus_req is de-asserted when root hub is
2380 * suspended or HNP is in progress.
2381 */
2382 pr_debug("!a_bus_req\n");
2383 msm_otg_del_timer(motg);
2384 otg->state = OTG_STATE_A_SUSPEND;
2385 if (otg->host->b_hnp_enable)
2386 msm_otg_start_timer(motg, TA_AIDL_BDIS,
2387 A_AIDL_BDIS);
2388 else
2389 pm_runtime_put_sync(otg->dev);
2390 } else if (!test_bit(B_CONN, &motg->inputs)) {
2391 pr_debug("!b_conn\n");
2392 msm_otg_del_timer(motg);
2393 otg->state = OTG_STATE_A_WAIT_BCON;
2394 if (TA_WAIT_BCON > 0)
2395 msm_otg_start_timer(motg, TA_WAIT_BCON,
2396 A_WAIT_BCON);
2397 if (msm_chg_check_aca_intr(motg))
2398 work = 1;
2399 } else if (test_bit(ID_A, &motg->inputs)) {
2400 msm_otg_del_timer(motg);
2401 msm_hsusb_vbus_power(motg, 0);
2402 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
2403 msm_otg_notify_charger(motg,
2404 IDEV_ACA_CHG_MAX);
2405 else
2406 msm_otg_notify_charger(motg,
2407 IDEV_CHG_MIN - motg->mA_port);
2408 } else if (!test_bit(ID, &motg->inputs)) {
2409 motg->chg_state = USB_CHG_STATE_UNDEFINED;
2410 motg->chg_type = USB_INVALID_CHARGER;
2411 msm_otg_notify_charger(motg, 0);
2412 msm_hsusb_vbus_power(motg, 1);
2413 }
2414 break;
2415 case OTG_STATE_A_SUSPEND:
2416 if ((test_bit(ID, &motg->inputs) &&
2417 !test_bit(ID_A, &motg->inputs)) ||
2418 test_bit(A_BUS_DROP, &motg->inputs) ||
2419 test_bit(A_AIDL_BDIS, &motg->tmouts)) {
2420 pr_debug("id_a/b/c || a_bus_drop ||"
2421 "a_aidl_bdis_tmout\n");
2422 msm_otg_del_timer(motg);
2423 clear_bit(B_CONN, &motg->inputs);
2424 otg->state = OTG_STATE_A_WAIT_VFALL;
2425 msm_otg_start_host(otg, 0);
2426 msm_otg_reset(otg);
2427 if (!test_bit(ID_A, &motg->inputs))
2428 msm_hsusb_vbus_power(motg, 0);
2429 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2430 } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
2431 pr_debug("!a_vbus_vld\n");
2432 msm_otg_del_timer(motg);
2433 clear_bit(B_CONN, &motg->inputs);
2434 otg->state = OTG_STATE_A_VBUS_ERR;
2435 msm_otg_start_host(otg, 0);
2436 msm_otg_reset(otg);
2437 } else if (!test_bit(B_CONN, &motg->inputs) &&
2438 otg->host->b_hnp_enable) {
2439 pr_debug("!b_conn && b_hnp_enable");
2440 otg->state = OTG_STATE_A_PERIPHERAL;
2441 msm_otg_host_hnp_enable(otg, 1);
2442 otg->gadget->is_a_peripheral = 1;
2443 msm_otg_start_peripheral(otg, 1);
2444 } else if (!test_bit(B_CONN, &motg->inputs) &&
2445 !otg->host->b_hnp_enable) {
2446 pr_debug("!b_conn && !b_hnp_enable");
2447 /*
2448 * bus request is dropped during suspend.
2449 * acquire again for next device.
2450 */
2451 set_bit(A_BUS_REQ, &motg->inputs);
2452 otg->state = OTG_STATE_A_WAIT_BCON;
2453 if (TA_WAIT_BCON > 0)
2454 msm_otg_start_timer(motg, TA_WAIT_BCON,
2455 A_WAIT_BCON);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002456 } else if (test_bit(ID_A, &motg->inputs)) {
Mayank Ranae3926882011-12-26 09:47:54 +05302457 msm_hsusb_vbus_power(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002458 msm_otg_notify_charger(motg,
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302459 IDEV_CHG_MIN - motg->mA_port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002460 } else if (!test_bit(ID, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002461 msm_otg_notify_charger(motg, 0);
Mayank Ranae3926882011-12-26 09:47:54 +05302462 msm_hsusb_vbus_power(motg, 1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302463 }
2464 break;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302465 case OTG_STATE_A_PERIPHERAL:
2466 if ((test_bit(ID, &motg->inputs) &&
2467 !test_bit(ID_A, &motg->inputs)) ||
2468 test_bit(A_BUS_DROP, &motg->inputs)) {
2469 pr_debug("id _f/b/c || a_bus_drop\n");
2470 /* Clear BIDL_ADIS timer */
2471 msm_otg_del_timer(motg);
2472 otg->state = OTG_STATE_A_WAIT_VFALL;
2473 msm_otg_start_peripheral(otg, 0);
2474 otg->gadget->is_a_peripheral = 0;
2475 msm_otg_start_host(otg, 0);
2476 msm_otg_reset(otg);
2477 if (!test_bit(ID_A, &motg->inputs))
2478 msm_hsusb_vbus_power(motg, 0);
2479 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2480 } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
2481 pr_debug("!a_vbus_vld\n");
2482 /* Clear BIDL_ADIS timer */
2483 msm_otg_del_timer(motg);
2484 otg->state = OTG_STATE_A_VBUS_ERR;
2485 msm_otg_start_peripheral(otg, 0);
2486 otg->gadget->is_a_peripheral = 0;
2487 msm_otg_start_host(otg, 0);
2488 } else if (test_bit(A_BIDL_ADIS, &motg->tmouts)) {
2489 pr_debug("a_bidl_adis_tmout\n");
2490 msm_otg_start_peripheral(otg, 0);
2491 otg->gadget->is_a_peripheral = 0;
2492 otg->state = OTG_STATE_A_WAIT_BCON;
2493 set_bit(A_BUS_REQ, &motg->inputs);
2494 msm_otg_host_hnp_enable(otg, 0);
2495 if (TA_WAIT_BCON > 0)
2496 msm_otg_start_timer(motg, TA_WAIT_BCON,
2497 A_WAIT_BCON);
2498 } else if (test_bit(ID_A, &motg->inputs)) {
2499 msm_hsusb_vbus_power(motg, 0);
2500 msm_otg_notify_charger(motg,
2501 IDEV_CHG_MIN - motg->mA_port);
2502 } else if (!test_bit(ID, &motg->inputs)) {
2503 msm_otg_notify_charger(motg, 0);
2504 msm_hsusb_vbus_power(motg, 1);
2505 }
2506 break;
2507 case OTG_STATE_A_WAIT_VFALL:
2508 if (test_bit(A_WAIT_VFALL, &motg->tmouts)) {
2509 clear_bit(A_VBUS_VLD, &motg->inputs);
2510 otg->state = OTG_STATE_A_IDLE;
2511 work = 1;
2512 }
2513 break;
2514 case OTG_STATE_A_VBUS_ERR:
2515 if ((test_bit(ID, &motg->inputs) &&
2516 !test_bit(ID_A, &motg->inputs)) ||
2517 test_bit(A_BUS_DROP, &motg->inputs) ||
2518 test_bit(A_CLR_ERR, &motg->inputs)) {
2519 otg->state = OTG_STATE_A_WAIT_VFALL;
2520 if (!test_bit(ID_A, &motg->inputs))
2521 msm_hsusb_vbus_power(motg, 0);
2522 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2523 motg->chg_state = USB_CHG_STATE_UNDEFINED;
2524 motg->chg_type = USB_INVALID_CHARGER;
2525 msm_otg_notify_charger(motg, 0);
2526 }
2527 break;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302528 default:
2529 break;
2530 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302531 if (work)
2532 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302533}
2534
2535static irqreturn_t msm_otg_irq(int irq, void *data)
2536{
2537 struct msm_otg *motg = data;
2538 struct otg_transceiver *otg = &motg->otg;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302539 u32 otgsc = 0, usbsts, pc;
2540 bool work = 0;
2541 irqreturn_t ret = IRQ_HANDLED;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302542
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302543 if (atomic_read(&motg->in_lpm)) {
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302544 pr_debug("OTG IRQ: in LPM\n");
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302545 disable_irq_nosync(irq);
2546 motg->async_int = 1;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302547 pm_request_resume(otg->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302548 return IRQ_HANDLED;
2549 }
2550
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002551 usbsts = readl(USB_USBSTS);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302552 otgsc = readl(USB_OTGSC);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302553
2554 if (!(otgsc & OTG_OTGSTS_MASK) && !(usbsts & OTG_USBSTS_MASK))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302555 return IRQ_NONE;
2556
2557 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302558 if (otgsc & OTGSC_ID) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302559 pr_debug("Id set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302560 set_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302561 } else {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302562 pr_debug("Id clear\n");
2563 /*
2564 * Assert a_bus_req to supply power on
2565 * VBUS when Micro/Mini-A cable is connected
2566 * with out user intervention.
2567 */
2568 set_bit(A_BUS_REQ, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302569 clear_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302570 msm_chg_enable_aca_det(motg);
2571 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302572 writel_relaxed(otgsc, USB_OTGSC);
2573 work = 1;
2574 } else if (otgsc & OTGSC_DPIS) {
2575 pr_debug("DPIS detected\n");
2576 writel_relaxed(otgsc, USB_OTGSC);
2577 set_bit(A_SRP_DET, &motg->inputs);
2578 set_bit(A_BUS_REQ, &motg->inputs);
2579 work = 1;
2580 } else if (otgsc & OTGSC_BSVIS) {
2581 writel_relaxed(otgsc, USB_OTGSC);
2582 /*
2583 * BSV interrupt comes when operating as an A-device
2584 * (VBUS on/off).
2585 * But, handle BSV when charger is removed from ACA in ID_A
2586 */
2587 if ((otg->state >= OTG_STATE_A_IDLE) &&
2588 !test_bit(ID_A, &motg->inputs))
2589 return IRQ_HANDLED;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302590 if (otgsc & OTGSC_BSV) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302591 pr_debug("BSV set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302592 set_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302593 } else {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302594 pr_debug("BSV clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302595 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302596 msm_chg_check_aca_intr(motg);
2597 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302598 work = 1;
2599 } else if (usbsts & STS_PCI) {
2600 pc = readl_relaxed(USB_PORTSC);
2601 pr_debug("portsc = %x\n", pc);
2602 ret = IRQ_NONE;
2603 /*
2604 * HCD Acks PCI interrupt. We use this to switch
2605 * between different OTG states.
2606 */
2607 work = 1;
2608 switch (otg->state) {
2609 case OTG_STATE_A_SUSPEND:
2610 if (otg->host->b_hnp_enable && (pc & PORTSC_CSC) &&
2611 !(pc & PORTSC_CCS)) {
2612 pr_debug("B_CONN clear\n");
2613 clear_bit(B_CONN, &motg->inputs);
2614 msm_otg_del_timer(motg);
2615 }
2616 break;
2617 case OTG_STATE_A_PERIPHERAL:
2618 /*
2619 * A-peripheral observed activity on bus.
2620 * clear A_BIDL_ADIS timer.
2621 */
2622 msm_otg_del_timer(motg);
2623 work = 0;
2624 break;
2625 case OTG_STATE_B_WAIT_ACON:
2626 if ((pc & PORTSC_CSC) && (pc & PORTSC_CCS)) {
2627 pr_debug("A_CONN set\n");
2628 set_bit(A_CONN, &motg->inputs);
2629 /* Clear ASE0_BRST timer */
2630 msm_otg_del_timer(motg);
2631 }
2632 break;
2633 case OTG_STATE_B_HOST:
2634 if ((pc & PORTSC_CSC) && !(pc & PORTSC_CCS)) {
2635 pr_debug("A_CONN clear\n");
2636 clear_bit(A_CONN, &motg->inputs);
2637 msm_otg_del_timer(motg);
2638 }
2639 break;
2640 case OTG_STATE_A_WAIT_BCON:
2641 if (TA_WAIT_BCON < 0)
2642 set_bit(A_BUS_REQ, &motg->inputs);
2643 default:
2644 work = 0;
2645 break;
2646 }
2647 } else if (usbsts & STS_URI) {
2648 ret = IRQ_NONE;
2649 switch (otg->state) {
2650 case OTG_STATE_A_PERIPHERAL:
2651 /*
2652 * A-peripheral observed activity on bus.
2653 * clear A_BIDL_ADIS timer.
2654 */
2655 msm_otg_del_timer(motg);
2656 work = 0;
2657 break;
2658 default:
2659 work = 0;
2660 break;
2661 }
2662 } else if (usbsts & STS_SLI) {
2663 ret = IRQ_NONE;
2664 work = 0;
2665 switch (otg->state) {
2666 case OTG_STATE_B_PERIPHERAL:
2667 if (otg->gadget->b_hnp_enable) {
2668 set_bit(A_BUS_SUSPEND, &motg->inputs);
2669 set_bit(B_BUS_REQ, &motg->inputs);
2670 work = 1;
2671 }
2672 break;
2673 case OTG_STATE_A_PERIPHERAL:
2674 msm_otg_start_timer(motg, TA_BIDL_ADIS,
2675 A_BIDL_ADIS);
2676 break;
2677 default:
2678 break;
2679 }
2680 } else if ((usbsts & PHY_ALT_INT)) {
2681 writel_relaxed(PHY_ALT_INT, USB_USBSTS);
2682 if (msm_chg_check_aca_intr(motg))
2683 work = 1;
2684 ret = IRQ_HANDLED;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302685 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302686 if (work)
2687 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302688
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302689 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002690}
2691
2692static void msm_otg_set_vbus_state(int online)
2693{
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302694 static bool init;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002695 struct msm_otg *motg = the_msm_otg;
2696
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302697 if (online) {
2698 pr_debug("PMIC: BSV set\n");
2699 set_bit(B_SESS_VLD, &motg->inputs);
2700 } else {
2701 pr_debug("PMIC: BSV clear\n");
2702 clear_bit(B_SESS_VLD, &motg->inputs);
2703 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002704
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302705 if (!init) {
2706 init = true;
2707 complete(&pmic_vbus_init);
2708 pr_debug("PMIC: BSV init complete\n");
2709 return;
2710 }
2711
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302712 queue_work(system_nrt_wq, &motg->sm_work);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002713}
2714
2715static irqreturn_t msm_pmic_id_irq(int irq, void *data)
2716{
2717 struct msm_otg *motg = data;
2718
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302719 if (aca_id_turned_on)
2720 return IRQ_HANDLED;
2721
2722 if (irq_read_line(motg->pdata->pmic_id_irq)) {
2723 pr_debug("PMIC: ID set\n");
2724 set_bit(ID, &motg->inputs);
2725 } else {
2726 pr_debug("PMIC: ID clear\n");
2727 clear_bit(ID, &motg->inputs);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302728 set_bit(A_BUS_REQ, &motg->inputs);
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302729 }
2730
2731 if (motg->otg.state != OTG_STATE_UNDEFINED)
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302732 queue_work(system_nrt_wq, &motg->sm_work);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002733
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302734 return IRQ_HANDLED;
2735}
2736
2737static int msm_otg_mode_show(struct seq_file *s, void *unused)
2738{
2739 struct msm_otg *motg = s->private;
2740 struct otg_transceiver *otg = &motg->otg;
2741
2742 switch (otg->state) {
2743 case OTG_STATE_A_HOST:
2744 seq_printf(s, "host\n");
2745 break;
2746 case OTG_STATE_B_PERIPHERAL:
2747 seq_printf(s, "peripheral\n");
2748 break;
2749 default:
2750 seq_printf(s, "none\n");
2751 break;
2752 }
2753
2754 return 0;
2755}
2756
2757static int msm_otg_mode_open(struct inode *inode, struct file *file)
2758{
2759 return single_open(file, msm_otg_mode_show, inode->i_private);
2760}
2761
2762static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
2763 size_t count, loff_t *ppos)
2764{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05302765 struct seq_file *s = file->private_data;
2766 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302767 char buf[16];
2768 struct otg_transceiver *otg = &motg->otg;
2769 int status = count;
2770 enum usb_mode_type req_mode;
2771
2772 memset(buf, 0x00, sizeof(buf));
2773
2774 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
2775 status = -EFAULT;
2776 goto out;
2777 }
2778
2779 if (!strncmp(buf, "host", 4)) {
2780 req_mode = USB_HOST;
2781 } else if (!strncmp(buf, "peripheral", 10)) {
2782 req_mode = USB_PERIPHERAL;
2783 } else if (!strncmp(buf, "none", 4)) {
2784 req_mode = USB_NONE;
2785 } else {
2786 status = -EINVAL;
2787 goto out;
2788 }
2789
2790 switch (req_mode) {
2791 case USB_NONE:
2792 switch (otg->state) {
2793 case OTG_STATE_A_HOST:
2794 case OTG_STATE_B_PERIPHERAL:
2795 set_bit(ID, &motg->inputs);
2796 clear_bit(B_SESS_VLD, &motg->inputs);
2797 break;
2798 default:
2799 goto out;
2800 }
2801 break;
2802 case USB_PERIPHERAL:
2803 switch (otg->state) {
2804 case OTG_STATE_B_IDLE:
2805 case OTG_STATE_A_HOST:
2806 set_bit(ID, &motg->inputs);
2807 set_bit(B_SESS_VLD, &motg->inputs);
2808 break;
2809 default:
2810 goto out;
2811 }
2812 break;
2813 case USB_HOST:
2814 switch (otg->state) {
2815 case OTG_STATE_B_IDLE:
2816 case OTG_STATE_B_PERIPHERAL:
2817 clear_bit(ID, &motg->inputs);
2818 break;
2819 default:
2820 goto out;
2821 }
2822 break;
2823 default:
2824 goto out;
2825 }
2826
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302827 pm_runtime_resume(otg->dev);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302828 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302829out:
2830 return status;
2831}
2832
2833const struct file_operations msm_otg_mode_fops = {
2834 .open = msm_otg_mode_open,
2835 .read = seq_read,
2836 .write = msm_otg_mode_write,
2837 .llseek = seq_lseek,
2838 .release = single_release,
2839};
2840
Chiranjeevi Velempatif9a11542012-03-28 18:18:34 +05302841static int msm_otg_show_otg_state(struct seq_file *s, void *unused)
2842{
2843 struct msm_otg *motg = s->private;
2844 struct otg_transceiver *otg = &motg->otg;
2845
2846 seq_printf(s, "%s\n", otg_state_string(otg->state));
2847 return 0;
2848}
2849
2850static int msm_otg_otg_state_open(struct inode *inode, struct file *file)
2851{
2852 return single_open(file, msm_otg_show_otg_state, inode->i_private);
2853}
2854
2855const struct file_operations msm_otg_state_fops = {
2856 .open = msm_otg_otg_state_open,
2857 .read = seq_read,
2858 .llseek = seq_lseek,
2859 .release = single_release,
2860};
2861
Anji jonnalad270e2d2011-08-09 11:28:32 +05302862static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
2863{
2864 struct msm_otg *motg = s->private;
2865
Pavankumar Kondeti9ef69cb2011-12-12 14:18:22 +05302866 seq_printf(s, "%s\n", chg_to_string(motg->chg_type));
Anji jonnalad270e2d2011-08-09 11:28:32 +05302867 return 0;
2868}
2869
2870static int msm_otg_chg_open(struct inode *inode, struct file *file)
2871{
2872 return single_open(file, msm_otg_show_chg_type, inode->i_private);
2873}
2874
2875const struct file_operations msm_otg_chg_fops = {
2876 .open = msm_otg_chg_open,
2877 .read = seq_read,
2878 .llseek = seq_lseek,
2879 .release = single_release,
2880};
2881
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302882static int msm_otg_aca_show(struct seq_file *s, void *unused)
2883{
2884 if (debug_aca_enabled)
2885 seq_printf(s, "enabled\n");
2886 else
2887 seq_printf(s, "disabled\n");
2888
2889 return 0;
2890}
2891
2892static int msm_otg_aca_open(struct inode *inode, struct file *file)
2893{
2894 return single_open(file, msm_otg_aca_show, inode->i_private);
2895}
2896
2897static ssize_t msm_otg_aca_write(struct file *file, const char __user *ubuf,
2898 size_t count, loff_t *ppos)
2899{
2900 char buf[8];
2901
2902 memset(buf, 0x00, sizeof(buf));
2903
2904 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
2905 return -EFAULT;
2906
2907 if (!strncmp(buf, "enable", 6))
2908 debug_aca_enabled = true;
2909 else
2910 debug_aca_enabled = false;
2911
2912 return count;
2913}
2914
2915const struct file_operations msm_otg_aca_fops = {
2916 .open = msm_otg_aca_open,
2917 .read = seq_read,
2918 .write = msm_otg_aca_write,
2919 .llseek = seq_lseek,
2920 .release = single_release,
2921};
2922
Manu Gautam8bdcc592012-03-06 11:26:06 +05302923static int msm_otg_bus_show(struct seq_file *s, void *unused)
2924{
2925 if (debug_bus_voting_enabled)
2926 seq_printf(s, "enabled\n");
2927 else
2928 seq_printf(s, "disabled\n");
2929
2930 return 0;
2931}
2932
2933static int msm_otg_bus_open(struct inode *inode, struct file *file)
2934{
2935 return single_open(file, msm_otg_bus_show, inode->i_private);
2936}
2937
2938static ssize_t msm_otg_bus_write(struct file *file, const char __user *ubuf,
2939 size_t count, loff_t *ppos)
2940{
2941 char buf[8];
2942 int ret;
2943 struct seq_file *s = file->private_data;
2944 struct msm_otg *motg = s->private;
2945
2946 memset(buf, 0x00, sizeof(buf));
2947
2948 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
2949 return -EFAULT;
2950
2951 if (!strncmp(buf, "enable", 6)) {
2952 /* Do not vote here. Let OTG statemachine decide when to vote */
2953 debug_bus_voting_enabled = true;
2954 } else {
2955 debug_bus_voting_enabled = false;
2956 if (motg->bus_perf_client) {
2957 ret = msm_bus_scale_client_update_request(
2958 motg->bus_perf_client, 0);
2959 if (ret)
2960 dev_err(motg->otg.dev, "%s: Failed to devote "
2961 "for bus bw %d\n", __func__, ret);
2962 }
2963 }
2964
2965 return count;
2966}
2967
2968const struct file_operations msm_otg_bus_fops = {
2969 .open = msm_otg_bus_open,
2970 .read = seq_read,
2971 .write = msm_otg_bus_write,
2972 .llseek = seq_lseek,
2973 .release = single_release,
2974};
2975
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302976static struct dentry *msm_otg_dbg_root;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302977
2978static int msm_otg_debugfs_init(struct msm_otg *motg)
2979{
Manu Gautam8bdcc592012-03-06 11:26:06 +05302980 struct dentry *msm_otg_dentry;
Anji jonnalad270e2d2011-08-09 11:28:32 +05302981
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302982 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
2983
2984 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
2985 return -ENODEV;
2986
Anji jonnalad270e2d2011-08-09 11:28:32 +05302987 if (motg->pdata->mode == USB_OTG &&
2988 motg->pdata->otg_control == OTG_USER_CONTROL) {
2989
Manu Gautam8bdcc592012-03-06 11:26:06 +05302990 msm_otg_dentry = debugfs_create_file("mode", S_IRUGO |
Anji jonnalad270e2d2011-08-09 11:28:32 +05302991 S_IWUSR, msm_otg_dbg_root, motg,
2992 &msm_otg_mode_fops);
2993
Manu Gautam8bdcc592012-03-06 11:26:06 +05302994 if (!msm_otg_dentry) {
Anji jonnalad270e2d2011-08-09 11:28:32 +05302995 debugfs_remove(msm_otg_dbg_root);
2996 msm_otg_dbg_root = NULL;
2997 return -ENODEV;
2998 }
2999 }
3000
Manu Gautam8bdcc592012-03-06 11:26:06 +05303001 msm_otg_dentry = debugfs_create_file("chg_type", S_IRUGO,
Anji jonnalad270e2d2011-08-09 11:28:32 +05303002 msm_otg_dbg_root, motg,
3003 &msm_otg_chg_fops);
3004
Manu Gautam8bdcc592012-03-06 11:26:06 +05303005 if (!msm_otg_dentry) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303006 debugfs_remove_recursive(msm_otg_dbg_root);
3007 return -ENODEV;
3008 }
3009
Manu Gautam8bdcc592012-03-06 11:26:06 +05303010 msm_otg_dentry = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303011 msm_otg_dbg_root, motg,
3012 &msm_otg_aca_fops);
3013
Manu Gautam8bdcc592012-03-06 11:26:06 +05303014 if (!msm_otg_dentry) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303015 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303016 return -ENODEV;
3017 }
3018
Manu Gautam8bdcc592012-03-06 11:26:06 +05303019 msm_otg_dentry = debugfs_create_file("bus_voting", S_IRUGO | S_IWUSR,
3020 msm_otg_dbg_root, motg,
3021 &msm_otg_bus_fops);
3022
3023 if (!msm_otg_dentry) {
3024 debugfs_remove_recursive(msm_otg_dbg_root);
3025 return -ENODEV;
3026 }
Chiranjeevi Velempatif9a11542012-03-28 18:18:34 +05303027
3028 msm_otg_dentry = debugfs_create_file("otg_state", S_IRUGO,
3029 msm_otg_dbg_root, motg, &msm_otg_state_fops);
3030
3031 if (!msm_otg_dentry) {
3032 debugfs_remove_recursive(msm_otg_dbg_root);
3033 return -ENODEV;
3034 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303035 return 0;
3036}
3037
3038static void msm_otg_debugfs_cleanup(void)
3039{
Anji jonnalad270e2d2011-08-09 11:28:32 +05303040 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303041}
3042
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303043static u64 msm_otg_dma_mask = DMA_BIT_MASK(64);
3044static struct platform_device *msm_otg_add_pdev(
3045 struct platform_device *ofdev, const char *name)
3046{
3047 struct platform_device *pdev;
3048 const struct resource *res = ofdev->resource;
3049 unsigned int num = ofdev->num_resources;
3050 int retval;
3051
3052 pdev = platform_device_alloc(name, -1);
3053 if (!pdev) {
3054 retval = -ENOMEM;
3055 goto error;
3056 }
3057
3058 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
3059 pdev->dev.dma_mask = &msm_otg_dma_mask;
3060
3061 if (num) {
3062 retval = platform_device_add_resources(pdev, res, num);
3063 if (retval)
3064 goto error;
3065 }
3066
3067 retval = platform_device_add(pdev);
3068 if (retval)
3069 goto error;
3070
3071 return pdev;
3072
3073error:
3074 platform_device_put(pdev);
3075 return ERR_PTR(retval);
3076}
3077
3078static int msm_otg_setup_devices(struct platform_device *ofdev,
3079 enum usb_mode_type mode, bool init)
3080{
3081 const char *gadget_name = "msm_hsusb";
3082 const char *host_name = "msm_hsusb_host";
3083 static struct platform_device *gadget_pdev;
3084 static struct platform_device *host_pdev;
3085 int retval = 0;
3086
3087 if (!init) {
3088 if (gadget_pdev)
3089 platform_device_unregister(gadget_pdev);
3090 if (host_pdev)
3091 platform_device_unregister(host_pdev);
3092 return 0;
3093 }
3094
3095 switch (mode) {
3096 case USB_OTG:
3097 /* fall through */
3098 case USB_PERIPHERAL:
3099 gadget_pdev = msm_otg_add_pdev(ofdev, gadget_name);
3100 if (IS_ERR(gadget_pdev)) {
3101 retval = PTR_ERR(gadget_pdev);
3102 break;
3103 }
3104 if (mode == USB_PERIPHERAL)
3105 break;
3106 /* fall through */
3107 case USB_HOST:
3108 host_pdev = msm_otg_add_pdev(ofdev, host_name);
3109 if (IS_ERR(host_pdev)) {
3110 retval = PTR_ERR(host_pdev);
3111 if (mode == USB_OTG)
3112 platform_device_unregister(gadget_pdev);
3113 }
3114 break;
3115 default:
3116 break;
3117 }
3118
3119 return retval;
3120}
3121
3122struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
3123{
3124 struct device_node *node = pdev->dev.of_node;
3125 struct msm_otg_platform_data *pdata;
3126 int len = 0;
3127
3128 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
3129 if (!pdata) {
3130 pr_err("unable to allocate platform data\n");
3131 return NULL;
3132 }
3133 of_get_property(node, "qcom,hsusb-otg-phy-init-seq", &len);
3134 if (len) {
3135 pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
3136 if (!pdata->phy_init_seq)
3137 return NULL;
3138 of_property_read_u32_array(node, "qcom,hsusb-otg-phy-init-seq",
3139 pdata->phy_init_seq,
3140 len/sizeof(*pdata->phy_init_seq));
3141 }
3142 of_property_read_u32(node, "qcom,hsusb-otg-power-budget",
3143 &pdata->power_budget);
3144 of_property_read_u32(node, "qcom,hsusb-otg-mode",
3145 &pdata->mode);
3146 of_property_read_u32(node, "qcom,hsusb-otg-otg-control",
3147 &pdata->otg_control);
3148 of_property_read_u32(node, "qcom,hsusb-otg-default-mode",
3149 &pdata->default_mode);
3150 of_property_read_u32(node, "qcom,hsusb-otg-phy-type",
3151 &pdata->phy_type);
3152 of_property_read_u32(node, "qcom,hsusb-otg-pmic-id-irq",
3153 &pdata->pmic_id_irq);
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303154 return pdata;
3155}
3156
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303157static int __init msm_otg_probe(struct platform_device *pdev)
3158{
3159 int ret = 0;
3160 struct resource *res;
3161 struct msm_otg *motg;
3162 struct otg_transceiver *otg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303163 struct msm_otg_platform_data *pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303164
3165 dev_info(&pdev->dev, "msm_otg probe\n");
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303166
3167 if (pdev->dev.of_node) {
3168 dev_dbg(&pdev->dev, "device tree enabled\n");
3169 pdata = msm_otg_dt_to_pdata(pdev);
3170 if (!pdata)
3171 return -ENOMEM;
3172 ret = msm_otg_setup_devices(pdev, pdata->mode, true);
3173 if (ret) {
3174 dev_err(&pdev->dev, "devices setup failed\n");
3175 return ret;
3176 }
3177 } else if (!pdev->dev.platform_data) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303178 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
3179 return -ENODEV;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303180 } else {
3181 pdata = pdev->dev.platform_data;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303182 }
3183
3184 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
3185 if (!motg) {
3186 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
3187 return -ENOMEM;
3188 }
3189
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003190 the_msm_otg = motg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303191 motg->pdata = pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303192 otg = &motg->otg;
3193 otg->dev = &pdev->dev;
3194
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303195 /*
3196 * ACA ID_GND threshold range is overlapped with OTG ID_FLOAT. Hence
3197 * PHY treat ACA ID_GND as float and no interrupt is generated. But
3198 * PMIC can detect ACA ID_GND and generate an interrupt.
3199 */
3200 if (aca_enabled() && motg->pdata->otg_control != OTG_PMIC_CONTROL) {
3201 dev_err(&pdev->dev, "ACA can not be enabled without PMIC\n");
3202 ret = -EINVAL;
3203 goto free_motg;
3204 }
3205
Ofir Cohen4da266f2012-01-03 10:19:29 +02003206 /* initialize reset counter */
3207 motg->reset_counter = 0;
3208
Amit Blay02eff132011-09-21 16:46:24 +03003209 /* Some targets don't support PHY clock. */
Manu Gautam5143b252012-01-05 19:25:23 -08003210 motg->phy_reset_clk = clk_get(&pdev->dev, "phy_clk");
Amit Blay02eff132011-09-21 16:46:24 +03003211 if (IS_ERR(motg->phy_reset_clk))
Manu Gautam5143b252012-01-05 19:25:23 -08003212 dev_err(&pdev->dev, "failed to get phy_clk\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303213
Pavankumar Kondeti923262e2012-04-20 15:34:24 +05303214 /*
3215 * Targets on which link uses asynchronous reset methodology,
3216 * free running clock is not required during the reset.
3217 */
Manu Gautam5143b252012-01-05 19:25:23 -08003218 motg->clk = clk_get(&pdev->dev, "alt_core_clk");
Pavankumar Kondeti923262e2012-04-20 15:34:24 +05303219 if (IS_ERR(motg->clk))
3220 dev_dbg(&pdev->dev, "alt_core_clk is not present\n");
3221 else
3222 clk_set_rate(motg->clk, 60000000);
Anji jonnala0f73cac2011-05-04 10:19:46 +05303223
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05303224 /* pm qos request to prevent apps idle power collapse */
3225 if (motg->pdata->swfi_latency)
3226 pm_qos_add_request(&motg->pm_qos_req_dma,
3227 PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
Manu Gautam5143b252012-01-05 19:25:23 -08003228
Anji jonnala0f73cac2011-05-04 10:19:46 +05303229 /*
Manu Gautam5143b252012-01-05 19:25:23 -08003230 * USB Core is running its protocol engine based on CORE CLK,
Anji jonnala0f73cac2011-05-04 10:19:46 +05303231 * CORE CLK must be running at >55Mhz for correct HSUSB
3232 * operation and USB core cannot tolerate frequency changes on
3233 * CORE CLK. For such USB cores, vote for maximum clk frequency
3234 * on pclk source
3235 */
Manu Gautam5143b252012-01-05 19:25:23 -08003236 motg->core_clk = clk_get(&pdev->dev, "core_clk");
3237 if (IS_ERR(motg->core_clk)) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303238 motg->core_clk = NULL;
Manu Gautam5143b252012-01-05 19:25:23 -08003239 dev_err(&pdev->dev, "failed to get core_clk\n");
Pavankumar Kondetibc541332012-04-20 15:32:04 +05303240 ret = PTR_ERR(motg->core_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08003241 goto put_clk;
3242 }
3243 clk_set_rate(motg->core_clk, INT_MAX);
3244
3245 motg->pclk = clk_get(&pdev->dev, "iface_clk");
3246 if (IS_ERR(motg->pclk)) {
3247 dev_err(&pdev->dev, "failed to get iface_clk\n");
3248 ret = PTR_ERR(motg->pclk);
3249 goto put_core_clk;
3250 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303251
3252 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3253 if (!res) {
3254 dev_err(&pdev->dev, "failed to get platform resource mem\n");
3255 ret = -ENODEV;
Manu Gautam5143b252012-01-05 19:25:23 -08003256 goto put_pclk;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303257 }
3258
3259 motg->regs = ioremap(res->start, resource_size(res));
3260 if (!motg->regs) {
3261 dev_err(&pdev->dev, "ioremap failed\n");
3262 ret = -ENOMEM;
Manu Gautam5143b252012-01-05 19:25:23 -08003263 goto put_pclk;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303264 }
3265 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
3266
3267 motg->irq = platform_get_irq(pdev, 0);
3268 if (!motg->irq) {
3269 dev_err(&pdev->dev, "platform_get_irq failed\n");
3270 ret = -ENODEV;
3271 goto free_regs;
3272 }
3273
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003274 motg->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, "usb");
Anji jonnala7da3f262011-12-02 17:22:14 -08003275 if (IS_ERR(motg->xo_handle)) {
3276 dev_err(&pdev->dev, "%s not able to get the handle "
3277 "to vote for TCXO D0 buffer\n", __func__);
3278 ret = PTR_ERR(motg->xo_handle);
3279 goto free_regs;
3280 }
3281
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003282 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
Anji jonnala7da3f262011-12-02 17:22:14 -08003283 if (ret) {
3284 dev_err(&pdev->dev, "%s failed to vote for TCXO "
3285 "D0 buffer%d\n", __func__, ret);
3286 goto free_xo_handle;
3287 }
3288
Manu Gautam28b1bac2012-01-30 16:43:06 +05303289 clk_prepare_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05303290
Mayank Rana248698c2012-04-19 00:03:16 +05303291 motg->vdd_type = VDDCX_CORNER;
3292 hsusb_vddcx = devm_regulator_get(motg->otg.dev, "hsusb_vdd_dig");
3293 if (IS_ERR(hsusb_vddcx)) {
3294 hsusb_vddcx = devm_regulator_get(motg->otg.dev, "HSUSB_VDDCX");
3295 if (IS_ERR(hsusb_vddcx)) {
3296 dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
3297 goto devote_xo_handle;
3298 }
3299 motg->vdd_type = VDDCX;
Anji jonnala11aa5c42011-05-04 10:19:48 +05303300 }
3301
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003302 ret = msm_hsusb_config_vddcx(1);
3303 if (ret) {
3304 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
Mayank Rana248698c2012-04-19 00:03:16 +05303305 goto devote_xo_handle;
3306 }
3307
3308 ret = regulator_enable(hsusb_vddcx);
3309 if (ret) {
3310 dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
3311 goto free_config_vddcx;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003312 }
3313
Anji jonnala11aa5c42011-05-04 10:19:48 +05303314 ret = msm_hsusb_ldo_init(motg, 1);
3315 if (ret) {
3316 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Mayank Rana248698c2012-04-19 00:03:16 +05303317 goto free_hsusb_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05303318 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003319
Mayank Rana9e9a2ac2012-03-24 04:05:28 +05303320 if (pdata->mhl_enable) {
3321 mhl_analog_switch = devm_regulator_get(motg->otg.dev,
3322 "mhl_ext_3p3v");
3323 if (IS_ERR(mhl_analog_switch)) {
3324 dev_err(&pdev->dev, "Unable to get mhl_analog_switch\n");
3325 goto free_ldo_init;
3326 }
3327 }
3328
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003329 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05303330 if (ret) {
3331 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003332 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05303333 }
Manu Gautam28b1bac2012-01-30 16:43:06 +05303334 clk_prepare_enable(motg->core_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303335
3336 writel(0, USB_USBINTR);
3337 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003338 /* Ensure that above STOREs are completed before enabling interrupts */
3339 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303340
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003341 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05303342 msm_otg_init_timer(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303343 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303344 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303345 setup_timer(&motg->id_timer, msm_otg_id_timer_func,
3346 (unsigned long) motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303347 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
3348 "msm_otg", motg);
3349 if (ret) {
3350 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003351 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303352 }
3353
3354 otg->init = msm_otg_reset;
3355 otg->set_host = msm_otg_set_host;
3356 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303357 otg->set_power = msm_otg_set_power;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05303358 otg->start_hnp = msm_otg_start_hnp;
3359 otg->start_srp = msm_otg_start_srp;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05303360 otg->set_suspend = msm_otg_set_suspend;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303361
3362 otg->io_ops = &msm_otg_io_ops;
3363
3364 ret = otg_set_transceiver(&motg->otg);
3365 if (ret) {
3366 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
3367 goto free_irq;
3368 }
3369
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05303370 if (motg->pdata->mode == USB_OTG &&
3371 motg->pdata->otg_control == OTG_PMIC_CONTROL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003372 if (motg->pdata->pmic_id_irq) {
3373 ret = request_irq(motg->pdata->pmic_id_irq,
3374 msm_pmic_id_irq,
3375 IRQF_TRIGGER_RISING |
3376 IRQF_TRIGGER_FALLING,
3377 "msm_otg", motg);
3378 if (ret) {
3379 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
3380 goto remove_otg;
3381 }
3382 } else {
3383 ret = -ENODEV;
3384 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
3385 goto remove_otg;
3386 }
3387 }
3388
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05303389 msm_hsusb_mhl_switch_enable(motg, 1);
3390
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303391 platform_set_drvdata(pdev, motg);
3392 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003393 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303394
Anji jonnalad270e2d2011-08-09 11:28:32 +05303395 ret = msm_otg_debugfs_init(motg);
3396 if (ret)
3397 dev_dbg(&pdev->dev, "mode debugfs file is"
3398 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303399
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003400 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
3401 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
3402
Amit Blay58b31472011-11-18 09:39:39 +02003403 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
3404 if (motg->pdata->otg_control == OTG_PMIC_CONTROL &&
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05303405 (!(motg->pdata->mode == USB_OTG) ||
3406 motg->pdata->pmic_id_irq))
Amit Blay58b31472011-11-18 09:39:39 +02003407 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
Vijayavardhan Vennapusa03171c72012-04-26 14:44:48 +05303408 ALLOW_PHY_RETENTION;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003409
Amit Blay58b31472011-11-18 09:39:39 +02003410 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
3411 motg->caps = ALLOW_PHY_RETENTION;
3412 }
3413
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003414 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303415 pm_runtime_set_active(&pdev->dev);
3416 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303417
Manu Gautamcd82e9d2011-12-20 14:17:28 +05303418 if (motg->pdata->bus_scale_table) {
3419 motg->bus_perf_client =
3420 msm_bus_scale_register_client(motg->pdata->bus_scale_table);
3421 if (!motg->bus_perf_client)
3422 dev_err(motg->otg.dev, "%s: Failed to register BUS "
3423 "scaling client!!\n", __func__);
Manu Gautam8bdcc592012-03-06 11:26:06 +05303424 else
3425 debug_bus_voting_enabled = true;
Manu Gautamcd82e9d2011-12-20 14:17:28 +05303426 }
3427
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303428 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003429
3430remove_otg:
3431 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303432free_irq:
3433 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003434destroy_wlock:
3435 wake_lock_destroy(&motg->wlock);
Manu Gautam28b1bac2012-01-30 16:43:06 +05303436 clk_disable_unprepare(motg->core_clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003437 msm_hsusb_ldo_enable(motg, 0);
3438free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05303439 msm_hsusb_ldo_init(motg, 0);
Mayank Rana248698c2012-04-19 00:03:16 +05303440free_hsusb_vddcx:
3441 regulator_disable(hsusb_vddcx);
3442free_config_vddcx:
3443 regulator_set_voltage(hsusb_vddcx,
3444 vdd_val[motg->vdd_type][VDD_NONE],
3445 vdd_val[motg->vdd_type][VDD_MAX]);
Anji jonnala7da3f262011-12-02 17:22:14 -08003446devote_xo_handle:
Manu Gautam28b1bac2012-01-30 16:43:06 +05303447 clk_disable_unprepare(motg->pclk);
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003448 msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
Anji jonnala7da3f262011-12-02 17:22:14 -08003449free_xo_handle:
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003450 msm_xo_put(motg->xo_handle);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303451free_regs:
3452 iounmap(motg->regs);
Manu Gautam5143b252012-01-05 19:25:23 -08003453put_pclk:
3454 clk_put(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303455put_core_clk:
Manu Gautam5143b252012-01-05 19:25:23 -08003456 clk_put(motg->core_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303457put_clk:
Pavankumar Kondeti923262e2012-04-20 15:34:24 +05303458 if (!IS_ERR(motg->clk))
3459 clk_put(motg->clk);
Amit Blay02eff132011-09-21 16:46:24 +03003460 if (!IS_ERR(motg->phy_reset_clk))
3461 clk_put(motg->phy_reset_clk);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303462free_motg:
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05303463 if (motg->pdata->swfi_latency)
3464 pm_qos_remove_request(&motg->pm_qos_req_dma);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303465 kfree(motg);
3466 return ret;
3467}
3468
3469static int __devexit msm_otg_remove(struct platform_device *pdev)
3470{
3471 struct msm_otg *motg = platform_get_drvdata(pdev);
3472 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303473 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303474
3475 if (otg->host || otg->gadget)
3476 return -EBUSY;
3477
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303478 if (pdev->dev.of_node)
3479 msm_otg_setup_devices(pdev, motg->pdata->mode, false);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003480 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
3481 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303482 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303483 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303484 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303485
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303486 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303487
3488 device_init_wakeup(&pdev->dev, 0);
3489 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003490 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303491
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05303492 msm_hsusb_mhl_switch_enable(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003493 if (motg->pdata->pmic_id_irq)
3494 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303495 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303496 free_irq(motg->irq, motg);
3497
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303498 /*
3499 * Put PHY in low power mode.
3500 */
3501 ulpi_read(otg, 0x14);
3502 ulpi_write(otg, 0x08, 0x09);
3503
3504 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
3505 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
3506 if (readl(USB_PORTSC) & PORTSC_PHCD)
3507 break;
3508 udelay(1);
3509 cnt++;
3510 }
3511 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
3512 dev_err(otg->dev, "Unable to suspend PHY\n");
3513
Manu Gautam28b1bac2012-01-30 16:43:06 +05303514 clk_disable_unprepare(motg->pclk);
3515 clk_disable_unprepare(motg->core_clk);
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003516 msm_xo_put(motg->xo_handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003517 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05303518 msm_hsusb_ldo_init(motg, 0);
Mayank Rana248698c2012-04-19 00:03:16 +05303519 regulator_disable(hsusb_vddcx);
3520 regulator_set_voltage(hsusb_vddcx,
3521 vdd_val[motg->vdd_type][VDD_NONE],
3522 vdd_val[motg->vdd_type][VDD_MAX]);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303523
3524 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303525 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303526
Amit Blay02eff132011-09-21 16:46:24 +03003527 if (!IS_ERR(motg->phy_reset_clk))
3528 clk_put(motg->phy_reset_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303529 clk_put(motg->pclk);
Pavankumar Kondeti923262e2012-04-20 15:34:24 +05303530 if (!IS_ERR(motg->clk))
3531 clk_put(motg->clk);
Manu Gautam5143b252012-01-05 19:25:23 -08003532 clk_put(motg->core_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303533
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05303534 if (motg->pdata->swfi_latency)
3535 pm_qos_remove_request(&motg->pm_qos_req_dma);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303536
Manu Gautamcd82e9d2011-12-20 14:17:28 +05303537 if (motg->bus_perf_client)
3538 msm_bus_scale_unregister_client(motg->bus_perf_client);
3539
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05303540 kfree(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303541 return 0;
3542}
3543
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303544#ifdef CONFIG_PM_RUNTIME
3545static int msm_otg_runtime_idle(struct device *dev)
3546{
3547 struct msm_otg *motg = dev_get_drvdata(dev);
3548 struct otg_transceiver *otg = &motg->otg;
3549
3550 dev_dbg(dev, "OTG runtime idle\n");
3551
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05303552 if (otg->state == OTG_STATE_UNDEFINED)
3553 return -EAGAIN;
3554 else
3555 return 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303556}
3557
3558static int msm_otg_runtime_suspend(struct device *dev)
3559{
3560 struct msm_otg *motg = dev_get_drvdata(dev);
3561
3562 dev_dbg(dev, "OTG runtime suspend\n");
3563 return msm_otg_suspend(motg);
3564}
3565
3566static int msm_otg_runtime_resume(struct device *dev)
3567{
3568 struct msm_otg *motg = dev_get_drvdata(dev);
3569
3570 dev_dbg(dev, "OTG runtime resume\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05303571 pm_runtime_get_noresume(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303572 return msm_otg_resume(motg);
3573}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303574#endif
3575
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303576#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303577static int msm_otg_pm_suspend(struct device *dev)
3578{
Jack Phamd44455a2012-04-10 16:23:49 -07003579 struct msm_otg *motg = dev_get_drvdata(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303580
3581 dev_dbg(dev, "OTG PM suspend\n");
Jack Phamd44455a2012-04-10 16:23:49 -07003582 return msm_otg_suspend(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303583}
3584
3585static int msm_otg_pm_resume(struct device *dev)
3586{
3587 struct msm_otg *motg = dev_get_drvdata(dev);
Jack Phamd44455a2012-04-10 16:23:49 -07003588 int ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303589
3590 dev_dbg(dev, "OTG PM resume\n");
Jack Phamd44455a2012-04-10 16:23:49 -07003591 ret = msm_otg_resume(motg);
3592 if (ret)
3593 return ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303594
Jack Phamd44455a2012-04-10 16:23:49 -07003595 /* Update runtime PM status */
3596 pm_runtime_disable(dev);
3597 pm_runtime_set_active(dev);
3598 pm_runtime_enable(dev);
3599
Gregory Beanebd8ca22011-10-11 12:02:35 -07003600 return 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303601}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303602#endif
3603
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303604#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303605static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303606 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
3607 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
3608 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303609};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303610#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303611
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303612static struct of_device_id msm_otg_dt_match[] = {
3613 { .compatible = "qcom,hsusb-otg",
3614 },
3615 {}
3616};
3617
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303618static struct platform_driver msm_otg_driver = {
3619 .remove = __devexit_p(msm_otg_remove),
3620 .driver = {
3621 .name = DRIVER_NAME,
3622 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303623#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303624 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303625#endif
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303626 .of_match_table = msm_otg_dt_match,
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303627 },
3628};
3629
3630static int __init msm_otg_init(void)
3631{
3632 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
3633}
3634
3635static void __exit msm_otg_exit(void)
3636{
3637 platform_driver_unregister(&msm_otg_driver);
3638}
3639
3640module_init(msm_otg_init);
3641module_exit(msm_otg_exit);
3642
3643MODULE_LICENSE("GPL v2");
3644MODULE_DESCRIPTION("MSM USB transceiver driver");