blob: 2f7e250639d7c332c39979007b99c934fe3c78f1 [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) {
540 /* Enable PMIC pull-up */
541 pm8xxx_usb_id_pullup(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530542 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700543
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530544 return 0;
545}
546
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +0530547static const char *timer_string(int bit)
548{
549 switch (bit) {
550 case A_WAIT_VRISE: return "a_wait_vrise";
551 case A_WAIT_VFALL: return "a_wait_vfall";
552 case B_SRP_FAIL: return "b_srp_fail";
553 case A_WAIT_BCON: return "a_wait_bcon";
554 case A_AIDL_BDIS: return "a_aidl_bdis";
555 case A_BIDL_ADIS: return "a_bidl_adis";
556 case B_ASE0_BRST: return "b_ase0_brst";
557 case A_TST_MAINT: return "a_tst_maint";
558 case B_TST_SRP: return "b_tst_srp";
559 case B_TST_CONFIG: return "b_tst_config";
560 default: return "UNDEFINED";
561 }
562}
563
564static enum hrtimer_restart msm_otg_timer_func(struct hrtimer *hrtimer)
565{
566 struct msm_otg *motg = container_of(hrtimer, struct msm_otg, timer);
567
568 switch (motg->active_tmout) {
569 case A_WAIT_VRISE:
570 /* TODO: use vbus_vld interrupt */
571 set_bit(A_VBUS_VLD, &motg->inputs);
572 break;
573 case A_TST_MAINT:
574 /* OTG PET: End session after TA_TST_MAINT */
575 set_bit(A_BUS_DROP, &motg->inputs);
576 break;
577 case B_TST_SRP:
578 /*
579 * OTG PET: Initiate SRP after TB_TST_SRP of
580 * previous session end.
581 */
582 set_bit(B_BUS_REQ, &motg->inputs);
583 break;
584 case B_TST_CONFIG:
585 clear_bit(A_CONN, &motg->inputs);
586 break;
587 default:
588 set_bit(motg->active_tmout, &motg->tmouts);
589 }
590
591 pr_debug("expired %s timer\n", timer_string(motg->active_tmout));
592 queue_work(system_nrt_wq, &motg->sm_work);
593 return HRTIMER_NORESTART;
594}
595
596static void msm_otg_del_timer(struct msm_otg *motg)
597{
598 int bit = motg->active_tmout;
599
600 pr_debug("deleting %s timer. remaining %lld msec\n", timer_string(bit),
601 div_s64(ktime_to_us(hrtimer_get_remaining(
602 &motg->timer)), 1000));
603 hrtimer_cancel(&motg->timer);
604 clear_bit(bit, &motg->tmouts);
605}
606
607static void msm_otg_start_timer(struct msm_otg *motg, int time, int bit)
608{
609 clear_bit(bit, &motg->tmouts);
610 motg->active_tmout = bit;
611 pr_debug("starting %s timer\n", timer_string(bit));
612 hrtimer_start(&motg->timer,
613 ktime_set(time / 1000, (time % 1000) * 1000000),
614 HRTIMER_MODE_REL);
615}
616
617static void msm_otg_init_timer(struct msm_otg *motg)
618{
619 hrtimer_init(&motg->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
620 motg->timer.function = msm_otg_timer_func;
621}
622
623static int msm_otg_start_hnp(struct otg_transceiver *otg)
624{
625 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
626
627 if (otg->state != OTG_STATE_A_HOST) {
628 pr_err("HNP can not be initiated in %s state\n",
629 otg_state_string(otg->state));
630 return -EINVAL;
631 }
632
633 pr_debug("A-Host: HNP initiated\n");
634 clear_bit(A_BUS_REQ, &motg->inputs);
635 queue_work(system_nrt_wq, &motg->sm_work);
636 return 0;
637}
638
639static int msm_otg_start_srp(struct otg_transceiver *otg)
640{
641 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
642 u32 val;
643 int ret = 0;
644
645 if (otg->state != OTG_STATE_B_IDLE) {
646 pr_err("SRP can not be initiated in %s state\n",
647 otg_state_string(otg->state));
648 ret = -EINVAL;
649 goto out;
650 }
651
652 if ((jiffies - motg->b_last_se0_sess) < msecs_to_jiffies(TB_SRP_INIT)) {
653 pr_debug("initial conditions of SRP are not met. Try again"
654 "after some time\n");
655 ret = -EAGAIN;
656 goto out;
657 }
658
659 pr_debug("B-Device SRP started\n");
660
661 /*
662 * PHY won't pull D+ high unless it detects Vbus valid.
663 * Since by definition, SRP is only done when Vbus is not valid,
664 * software work-around needs to be used to spoof the PHY into
665 * thinking it is valid. This can be done using the VBUSVLDEXTSEL and
666 * VBUSVLDEXT register bits.
667 */
668 ulpi_write(otg, 0x03, 0x97);
669 /*
670 * Harware auto assist data pulsing: Data pulse is given
671 * for 7msec; wait for vbus
672 */
673 val = readl_relaxed(USB_OTGSC);
674 writel_relaxed((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, USB_OTGSC);
675
676 /* VBUS plusing is obsoleted in OTG 2.0 supplement */
677out:
678 return ret;
679}
680
681static void msm_otg_host_hnp_enable(struct otg_transceiver *otg, bool enable)
682{
683 struct usb_hcd *hcd = bus_to_hcd(otg->host);
684 struct usb_device *rhub = otg->host->root_hub;
685
686 if (enable) {
687 pm_runtime_disable(&rhub->dev);
688 rhub->state = USB_STATE_NOTATTACHED;
689 hcd->driver->bus_suspend(hcd);
690 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
691 } else {
692 usb_remove_hcd(hcd);
693 msm_otg_reset(otg);
694 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
695 }
696}
697
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530698static int msm_otg_set_suspend(struct otg_transceiver *otg, int suspend)
699{
700 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
701
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +0530702 if (aca_enabled() || (test_bit(ID, &motg->inputs) &&
703 !test_bit(ID_A, &motg->inputs)))
704 return 0;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530705
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +0530706 if (suspend) {
707 switch (otg->state) {
708 case OTG_STATE_A_WAIT_BCON:
709 if (TA_WAIT_BCON > 0)
710 break;
711 /* fall through */
712 case OTG_STATE_A_HOST:
713 pr_debug("host bus suspend\n");
714 clear_bit(A_BUS_REQ, &motg->inputs);
715 queue_work(system_nrt_wq, &motg->sm_work);
716 break;
717 default:
718 break;
719 }
720 } else {
721 switch (otg->state) {
722 case OTG_STATE_A_SUSPEND:
723 /* Remote wakeup or resume */
724 set_bit(A_BUS_REQ, &motg->inputs);
725 otg->state = OTG_STATE_A_HOST;
726 break;
727 default:
728 break;
729 }
730 }
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530731 return 0;
732}
733
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530734#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530735#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
736
737#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530738static int msm_otg_suspend(struct msm_otg *motg)
739{
740 struct otg_transceiver *otg = &motg->otg;
741 struct usb_bus *bus = otg->host;
742 struct msm_otg_platform_data *pdata = motg->pdata;
743 int cnt = 0;
Pavankumar Kondeti283146f2012-01-12 12:51:19 +0530744 bool host_bus_suspend, dcp;
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530745 u32 phy_ctrl_val = 0, cmd_val;
Stephen Boyd30ad10b2012-03-01 14:51:04 -0800746 unsigned ret;
Rajkumar Raghupathy242565d2011-12-13 12:10:59 +0530747 u32 portsc;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530748
749 if (atomic_read(&motg->in_lpm))
750 return 0;
751
752 disable_irq(motg->irq);
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530753 host_bus_suspend = otg->host && !test_bit(ID, &motg->inputs);
Pavankumar Kondeti283146f2012-01-12 12:51:19 +0530754 dcp = motg->chg_type == USB_DCP_CHARGER;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530755 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530756 * Chipidea 45-nm PHY suspend sequence:
757 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530758 * Interrupt Latch Register auto-clear feature is not present
759 * in all PHY versions. Latch register is clear on read type.
760 * Clear latch register to avoid spurious wakeup from
761 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530762 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530763 * PHY comparators are disabled when PHY enters into low power
764 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
765 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
766 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530767 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530768 * PLL is not turned off when PHY enters into low power mode (LPM).
769 * Disable PLL for maximum power savings.
770 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530771
772 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
773 ulpi_read(otg, 0x14);
774 if (pdata->otg_control == OTG_PHY_CONTROL)
775 ulpi_write(otg, 0x01, 0x30);
776 ulpi_write(otg, 0x08, 0x09);
777 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530778
779 /*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700780 * Turn off the OTG comparators, if depends on PMIC for
781 * VBUS and ID notifications.
782 */
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530783 if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !host_bus_suspend) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784 ulpi_write(otg, OTG_COMP_DISABLE,
785 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
786 motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
787 }
788
Rajkumar Raghupathy242565d2011-12-13 12:10:59 +0530789 /* Set the PHCD bit, only if it is not set by the controller.
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530790 * PHY may take some time or even fail to enter into low power
791 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
792 * in failure case.
793 */
Rajkumar Raghupathy242565d2011-12-13 12:10:59 +0530794 portsc = readl_relaxed(USB_PORTSC);
795 if (!(portsc & PORTSC_PHCD)) {
796 writel_relaxed(portsc | PORTSC_PHCD,
797 USB_PORTSC);
798 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
799 if (readl_relaxed(USB_PORTSC) & PORTSC_PHCD)
800 break;
801 udelay(1);
802 cnt++;
803 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530804 }
805
806 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
807 dev_err(otg->dev, "Unable to suspend PHY\n");
808 msm_otg_reset(otg);
809 enable_irq(motg->irq);
810 return -ETIMEDOUT;
811 }
812
813 /*
814 * PHY has capability to generate interrupt asynchronously in low
815 * power mode (LPM). This interrupt is level triggered. So USB IRQ
816 * line must be disabled till async interrupt enable bit is cleared
817 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
818 * block data communication from PHY.
Pavankumar Kondeti6be675f2012-04-16 13:29:24 +0530819 *
820 * PHY retention mode is disallowed while entering to LPM with wall
821 * charger connected. But PHY is put into suspend mode. Hence
822 * enable asynchronous interrupt to detect charger disconnection when
823 * PMIC notifications are unavailable.
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530824 */
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530825 cmd_val = readl_relaxed(USB_USBCMD);
Pavankumar Kondeti6be675f2012-04-16 13:29:24 +0530826 if (host_bus_suspend || (motg->pdata->otg_control == OTG_PHY_CONTROL &&
827 dcp))
Pavankumar Kondeti4960f312011-12-06 15:46:14 +0530828 cmd_val |= ASYNC_INTR_CTRL | ULPI_STP_CTRL;
829 else
830 cmd_val |= ULPI_STP_CTRL;
831 writel_relaxed(cmd_val, USB_USBCMD);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530832
Pavankumar Kondeti283146f2012-01-12 12:51:19 +0530833 /*
834 * BC1.2 spec mandates PD to enable VDP_SRC when charging from DCP.
835 * PHY retention and collapse can not happen with VDP_SRC enabled.
836 */
837 if (motg->caps & ALLOW_PHY_RETENTION && !host_bus_suspend && !dcp) {
Amit Blay58b31472011-11-18 09:39:39 +0200838 phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
839 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
840 /* Enable PHY HV interrupts to wake MPM/Link */
841 phy_ctrl_val |=
842 (PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
843
844 writel_relaxed(phy_ctrl_val & ~PHY_RETEN, USB_PHY_CTRL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700845 motg->lpm_flags |= PHY_RETENTIONED;
846 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530847
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700848 /* Ensure that above operation is completed before turning off clocks */
849 mb();
Manu Gautam28b1bac2012-01-30 16:43:06 +0530850 clk_disable_unprepare(motg->pclk);
851 clk_disable_unprepare(motg->core_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +0530852
Anji jonnala7da3f262011-12-02 17:22:14 -0800853 /* usb phy no more require TCXO clock, hence vote for TCXO disable */
Stephen Boyd30ad10b2012-03-01 14:51:04 -0800854 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
855 if (ret)
856 dev_err(otg->dev, "%s failed to devote for "
857 "TCXO D0 buffer%d\n", __func__, ret);
Anji jonnala7da3f262011-12-02 17:22:14 -0800858
Pavankumar Kondeti283146f2012-01-12 12:51:19 +0530859 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE &&
860 !host_bus_suspend && !dcp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700861 msm_hsusb_ldo_enable(motg, 0);
862 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530863 }
864
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530865 if (motg->lpm_flags & PHY_RETENTIONED) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700866 msm_hsusb_config_vddcx(0);
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530867 msm_hsusb_mhl_switch_enable(motg, 0);
868 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700869
870 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530871 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872 if (motg->pdata->pmic_id_irq)
873 enable_irq_wake(motg->pdata->pmic_id_irq);
874 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530875 if (bus)
876 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
877
878 atomic_set(&motg->in_lpm, 1);
879 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700880 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530881
882 dev_info(otg->dev, "USB in low power mode\n");
883
884 return 0;
885}
886
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530887static int msm_otg_resume(struct msm_otg *motg)
888{
889 struct otg_transceiver *otg = &motg->otg;
890 struct usb_bus *bus = otg->host;
891 int cnt = 0;
892 unsigned temp;
Amit Blay58b31472011-11-18 09:39:39 +0200893 u32 phy_ctrl_val = 0;
Anji jonnala7da3f262011-12-02 17:22:14 -0800894 unsigned ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530895
896 if (!atomic_read(&motg->in_lpm))
897 return 0;
898
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899 wake_lock(&motg->wlock);
Anji jonnala7da3f262011-12-02 17:22:14 -0800900
901 /* Vote for TCXO when waking up the phy */
Stephen Boyd30ad10b2012-03-01 14:51:04 -0800902 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
Anji jonnala7da3f262011-12-02 17:22:14 -0800903 if (ret)
904 dev_err(otg->dev, "%s failed to vote for "
905 "TCXO D0 buffer%d\n", __func__, ret);
906
Manu Gautam28b1bac2012-01-30 16:43:06 +0530907 clk_prepare_enable(motg->core_clk);
Amit Blay137575f2011-11-06 15:20:54 +0200908
Manu Gautam28b1bac2012-01-30 16:43:06 +0530909 clk_prepare_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530910
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700911 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
912 msm_hsusb_ldo_enable(motg, 1);
913 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
914 }
915
916 if (motg->lpm_flags & PHY_RETENTIONED) {
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530917 msm_hsusb_mhl_switch_enable(motg, 1);
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530918 msm_hsusb_config_vddcx(1);
Amit Blay58b31472011-11-18 09:39:39 +0200919 phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
920 phy_ctrl_val |= PHY_RETEN;
921 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
922 /* Disable PHY HV interrupts */
923 phy_ctrl_val &=
924 ~(PHY_IDHV_INTEN | PHY_OTGSESSVLDHV_INTEN);
925 writel_relaxed(phy_ctrl_val, USB_PHY_CTRL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700926 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530927 }
928
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530929 temp = readl(USB_USBCMD);
930 temp &= ~ASYNC_INTR_CTRL;
931 temp &= ~ULPI_STP_CTRL;
932 writel(temp, USB_USBCMD);
933
934 /*
935 * PHY comes out of low power mode (LPM) in case of wakeup
936 * from asynchronous interrupt.
937 */
938 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
939 goto skip_phy_resume;
940
941 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
942 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
943 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
944 break;
945 udelay(1);
946 cnt++;
947 }
948
949 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
950 /*
951 * This is a fatal error. Reset the link and
952 * PHY. USB state can not be restored. Re-insertion
953 * of USB cable is the only way to get USB working.
954 */
955 dev_err(otg->dev, "Unable to resume USB."
956 "Re-plugin the cable\n");
957 msm_otg_reset(otg);
958 }
959
960skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700961 /* Turn on the OTG comparators on resume */
962 if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
963 ulpi_write(otg, OTG_COMP_DISABLE,
964 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
965 motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
966 }
967 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530968 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700969 if (motg->pdata->pmic_id_irq)
970 disable_irq_wake(motg->pdata->pmic_id_irq);
971 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530972 if (bus)
973 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
974
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530975 atomic_set(&motg->in_lpm, 0);
976
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530977 if (motg->async_int) {
978 motg->async_int = 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530979 enable_irq(motg->irq);
980 }
981
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530982 dev_info(otg->dev, "USB exited from low power mode\n");
983
984 return 0;
985}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530986#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530987
David Keitel081a3e22012-04-18 12:37:07 -0700988static int msm_otg_notify_chg_type(struct msm_otg *motg)
989{
990 static int charger_type;
991 /*
992 * TODO
993 * Unify OTG driver charger types and power supply charger types
994 */
995 if (charger_type == motg->chg_type)
996 return 0;
997
998 if (motg->chg_type == USB_SDP_CHARGER)
999 charger_type = POWER_SUPPLY_TYPE_USB;
1000 else if (motg->chg_type == USB_CDP_CHARGER)
1001 charger_type = POWER_SUPPLY_TYPE_USB_CDP;
1002 else if (motg->chg_type == USB_DCP_CHARGER)
1003 charger_type = POWER_SUPPLY_TYPE_USB_DCP;
1004 else if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
1005 motg->chg_type == USB_ACA_A_CHARGER ||
1006 motg->chg_type == USB_ACA_B_CHARGER ||
1007 motg->chg_type == USB_ACA_C_CHARGER))
1008 charger_type = POWER_SUPPLY_TYPE_USB_ACA;
1009 else
1010 charger_type = POWER_SUPPLY_TYPE_BATTERY;
1011
1012 return pm8921_set_usb_power_supply_type(charger_type);
1013}
1014
Amit Blay0f7edf72012-01-15 10:11:27 +02001015static int msm_otg_notify_power_supply(struct msm_otg *motg, unsigned mA)
1016{
1017 struct power_supply *psy;
1018
1019 psy = power_supply_get_by_name("usb");
1020 if (!psy)
1021 goto psy_not_supported;
1022
1023 if (motg->cur_power == 0 && mA > 0) {
1024 /* Enable charging */
1025 if (power_supply_set_online(psy, true))
1026 goto psy_not_supported;
1027 } else if (motg->cur_power > 0 && mA == 0) {
1028 /* Disable charging */
1029 if (power_supply_set_online(psy, false))
1030 goto psy_not_supported;
1031 return 0;
1032 }
1033 /* Set max current limit */
1034 if (power_supply_set_current_limit(psy, 1000*mA))
1035 goto psy_not_supported;
1036
1037 return 0;
1038
1039psy_not_supported:
1040 dev_dbg(motg->otg.dev, "Power Supply doesn't support USB charger\n");
1041 return -ENXIO;
1042}
1043
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301044static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
1045{
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301046 struct usb_gadget *g = motg->otg.gadget;
1047
1048 if (g && g->is_a_peripheral)
1049 return;
1050
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301051 if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
1052 motg->chg_type == USB_ACA_A_CHARGER ||
1053 motg->chg_type == USB_ACA_B_CHARGER ||
1054 motg->chg_type == USB_ACA_C_CHARGER) &&
1055 mA > IDEV_ACA_CHG_LIMIT)
1056 mA = IDEV_ACA_CHG_LIMIT;
1057
David Keitel081a3e22012-04-18 12:37:07 -07001058 if (msm_otg_notify_chg_type(motg))
1059 dev_err(motg->otg.dev,
1060 "Failed notifying %d charger type to PMIC\n",
1061 motg->chg_type);
1062
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301063 if (motg->cur_power == mA)
1064 return;
1065
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301066 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Amit Blay0f7edf72012-01-15 10:11:27 +02001067
1068 /*
1069 * Use Power Supply API if supported, otherwise fallback
1070 * to legacy pm8921 API.
1071 */
1072 if (msm_otg_notify_power_supply(motg, mA))
1073 pm8921_charger_vbus_draw(mA);
1074
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301075 motg->cur_power = mA;
1076}
1077
1078static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
1079{
1080 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1081
1082 /*
1083 * Gadget driver uses set_power method to notify about the
1084 * available current based on suspend/configured states.
1085 *
1086 * IDEV_CHG can be drawn irrespective of suspend/un-configured
1087 * states when CDP/ACA is connected.
1088 */
1089 if (motg->chg_type == USB_SDP_CHARGER)
1090 msm_otg_notify_charger(motg, mA);
1091
1092 return 0;
1093}
1094
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301095static void msm_otg_start_host(struct otg_transceiver *otg, int on)
1096{
1097 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1098 struct msm_otg_platform_data *pdata = motg->pdata;
1099 struct usb_hcd *hcd;
1100
1101 if (!otg->host)
1102 return;
1103
1104 hcd = bus_to_hcd(otg->host);
1105
1106 if (on) {
1107 dev_dbg(otg->dev, "host on\n");
1108
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301109 /*
1110 * Some boards have a switch cotrolled by gpio
1111 * to enable/disable internal HUB. Enable internal
1112 * HUB before kicking the host.
1113 */
1114 if (pdata->setup_gpio)
1115 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301116 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301117 } else {
1118 dev_dbg(otg->dev, "host off\n");
1119
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301120 usb_remove_hcd(hcd);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301121 /* HCD core reset all bits of PORTSC. select ULPI phy */
1122 writel_relaxed(0x80000000, USB_PORTSC);
1123
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301124 if (pdata->setup_gpio)
1125 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301126 }
1127}
1128
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001129static int msm_otg_usbdev_notify(struct notifier_block *self,
1130 unsigned long action, void *priv)
1131{
1132 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301133 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301134 struct usb_device *udev = priv;
1135
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301136 if (action == USB_BUS_ADD || action == USB_BUS_REMOVE)
1137 goto out;
1138
1139 if (udev->bus != motg->otg.host)
1140 goto out;
1141 /*
1142 * Interested in devices connected directly to the root hub.
1143 * ACA dock can supply IDEV_CHG irrespective devices connected
1144 * on the accessory port.
1145 */
1146 if (!udev->parent || udev->parent->parent ||
1147 motg->chg_type == USB_ACA_DOCK_CHARGER)
1148 goto out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001149
1150 switch (action) {
1151 case USB_DEVICE_ADD:
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301152 if (aca_enabled())
1153 usb_disable_autosuspend(udev);
1154 if (otg->state == OTG_STATE_A_WAIT_BCON) {
1155 pr_debug("B_CONN set\n");
1156 set_bit(B_CONN, &motg->inputs);
1157 msm_otg_del_timer(motg);
1158 otg->state = OTG_STATE_A_HOST;
1159 /*
1160 * OTG PET: A-device must end session within
1161 * 10 sec after PET enumeration.
1162 */
1163 if (udev->quirks & USB_QUIRK_OTG_PET)
1164 msm_otg_start_timer(motg, TA_TST_MAINT,
1165 A_TST_MAINT);
1166 }
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301167 /* fall through */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001168 case USB_DEVICE_CONFIG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001169 if (udev->actconfig)
1170 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
1171 else
1172 motg->mA_port = IUNIT;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301173 if (otg->state == OTG_STATE_B_HOST)
1174 msm_otg_del_timer(motg);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301175 break;
1176 case USB_DEVICE_REMOVE:
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301177 if ((otg->state == OTG_STATE_A_HOST) ||
1178 (otg->state == OTG_STATE_A_SUSPEND)) {
1179 pr_debug("B_CONN clear\n");
1180 clear_bit(B_CONN, &motg->inputs);
1181 /*
1182 * OTG PET: A-device must end session after
1183 * PET disconnection if it is enumerated
1184 * with bcdDevice[0] = 1. USB core sets
1185 * bus->otg_vbus_off for us. clear it here.
1186 */
1187 if (udev->bus->otg_vbus_off) {
1188 udev->bus->otg_vbus_off = 0;
1189 set_bit(A_BUS_DROP, &motg->inputs);
1190 }
1191 queue_work(system_nrt_wq, &motg->sm_work);
1192 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001193 default:
1194 break;
1195 }
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301196 if (test_bit(ID_A, &motg->inputs))
1197 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX -
1198 motg->mA_port);
1199out:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001200 return NOTIFY_OK;
1201}
1202
Mayank Ranae3926882011-12-26 09:47:54 +05301203static void msm_hsusb_vbus_power(struct msm_otg *motg, bool on)
1204{
1205 int ret;
1206 static bool vbus_is_on;
1207
1208 if (vbus_is_on == on)
1209 return;
1210
1211 if (motg->pdata->vbus_power) {
Mayank Rana91f597e2012-01-20 10:12:06 +05301212 ret = motg->pdata->vbus_power(on);
1213 if (!ret)
1214 vbus_is_on = on;
Mayank Ranae3926882011-12-26 09:47:54 +05301215 return;
1216 }
1217
1218 if (!vbus_otg) {
1219 pr_err("vbus_otg is NULL.");
1220 return;
1221 }
1222
Abhijeet Dharmapurikarbe054882012-01-03 20:27:07 -08001223 /*
1224 * if entering host mode tell the charger to not draw any current
1225 * from usb - if exiting host mode let the charger draw current
1226 */
1227 pm8921_disable_source_current(on);
Mayank Ranae3926882011-12-26 09:47:54 +05301228 if (on) {
1229 ret = regulator_enable(vbus_otg);
1230 if (ret) {
1231 pr_err("unable to enable vbus_otg\n");
1232 return;
1233 }
1234 vbus_is_on = true;
1235 } else {
1236 ret = regulator_disable(vbus_otg);
1237 if (ret) {
1238 pr_err("unable to disable vbus_otg\n");
1239 return;
1240 }
1241 vbus_is_on = false;
1242 }
1243}
1244
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301245static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
1246{
1247 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1248 struct usb_hcd *hcd;
1249
1250 /*
1251 * Fail host registration if this board can support
1252 * only peripheral configuration.
1253 */
1254 if (motg->pdata->mode == USB_PERIPHERAL) {
1255 dev_info(otg->dev, "Host mode is not supported\n");
1256 return -ENODEV;
1257 }
1258
Mayank Ranae3926882011-12-26 09:47:54 +05301259 if (!motg->pdata->vbus_power && host) {
Mayank Rana9e9a2ac2012-03-24 04:05:28 +05301260 vbus_otg = devm_regulator_get(motg->otg.dev, "vbus_otg");
Mayank Ranae3926882011-12-26 09:47:54 +05301261 if (IS_ERR(vbus_otg)) {
1262 pr_err("Unable to get vbus_otg\n");
1263 return -ENODEV;
1264 }
1265 }
1266
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301267 if (!host) {
1268 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301269 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001270 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301271 msm_otg_start_host(otg, 0);
Mayank Ranae3926882011-12-26 09:47:54 +05301272 msm_hsusb_vbus_power(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301273 otg->host = NULL;
1274 otg->state = OTG_STATE_UNDEFINED;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301275 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301276 } else {
1277 otg->host = NULL;
1278 }
1279
1280 return 0;
1281 }
1282
1283 hcd = bus_to_hcd(host);
1284 hcd->power_budget = motg->pdata->power_budget;
1285
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301286#ifdef CONFIG_USB_OTG
1287 host->otg_port = 1;
1288#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001289 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
1290 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301291 otg->host = host;
1292 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
1293
1294 /*
1295 * Kick the state machine work, if peripheral is not supported
1296 * or peripheral is already registered with us.
1297 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301298 if (motg->pdata->mode == USB_HOST || otg->gadget) {
1299 pm_runtime_get_sync(otg->dev);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301300 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301301 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301302
1303 return 0;
1304}
1305
1306static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
1307{
Manu Gautamcd82e9d2011-12-20 14:17:28 +05301308 int ret;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301309 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1310 struct msm_otg_platform_data *pdata = motg->pdata;
1311
1312 if (!otg->gadget)
1313 return;
1314
1315 if (on) {
1316 dev_dbg(otg->dev, "gadget on\n");
1317 /*
1318 * Some boards have a switch cotrolled by gpio
1319 * to enable/disable internal HUB. Disable internal
1320 * HUB before kicking the gadget.
1321 */
1322 if (pdata->setup_gpio)
1323 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05301324 /*
1325 * vote for minimum dma_latency to prevent idle
1326 * power collapse(pc) while running in peripheral mode.
1327 */
1328 otg_pm_qos_update_latency(motg, 1);
Manu Gautamcd82e9d2011-12-20 14:17:28 +05301329 /* Configure BUS performance parameters for MAX bandwidth */
Manu Gautam8bdcc592012-03-06 11:26:06 +05301330 if (motg->bus_perf_client && debug_bus_voting_enabled) {
Manu Gautamcd82e9d2011-12-20 14:17:28 +05301331 ret = msm_bus_scale_client_update_request(
1332 motg->bus_perf_client, 1);
1333 if (ret)
1334 dev_err(motg->otg.dev, "%s: Failed to vote for "
1335 "bus bandwidth %d\n", __func__, ret);
1336 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301337 usb_gadget_vbus_connect(otg->gadget);
1338 } else {
1339 dev_dbg(otg->dev, "gadget off\n");
1340 usb_gadget_vbus_disconnect(otg->gadget);
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05301341 otg_pm_qos_update_latency(motg, 0);
Manu Gautamcd82e9d2011-12-20 14:17:28 +05301342 /* Configure BUS performance parameters to default */
1343 if (motg->bus_perf_client) {
1344 ret = msm_bus_scale_client_update_request(
1345 motg->bus_perf_client, 0);
1346 if (ret)
1347 dev_err(motg->otg.dev, "%s: Failed to devote "
1348 "for bus bw %d\n", __func__, ret);
1349 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301350 if (pdata->setup_gpio)
1351 pdata->setup_gpio(OTG_STATE_UNDEFINED);
1352 }
1353
1354}
1355
1356static int msm_otg_set_peripheral(struct otg_transceiver *otg,
1357 struct usb_gadget *gadget)
1358{
1359 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
1360
1361 /*
1362 * Fail peripheral registration if this board can support
1363 * only host configuration.
1364 */
1365 if (motg->pdata->mode == USB_HOST) {
1366 dev_info(otg->dev, "Peripheral mode is not supported\n");
1367 return -ENODEV;
1368 }
1369
1370 if (!gadget) {
1371 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301372 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301373 msm_otg_start_peripheral(otg, 0);
1374 otg->gadget = NULL;
1375 otg->state = OTG_STATE_UNDEFINED;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301376 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301377 } else {
1378 otg->gadget = NULL;
1379 }
1380
1381 return 0;
1382 }
1383 otg->gadget = gadget;
1384 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
1385
1386 /*
1387 * Kick the state machine work, if host is not supported
1388 * or host is already registered with us.
1389 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301390 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
1391 pm_runtime_get_sync(otg->dev);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301392 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301393 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301394
1395 return 0;
1396}
1397
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001398static bool msm_chg_aca_detect(struct msm_otg *motg)
1399{
1400 struct otg_transceiver *otg = &motg->otg;
1401 u32 int_sts;
1402 bool ret = false;
1403
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301404 if (!aca_enabled())
1405 goto out;
1406
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001407 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
1408 goto out;
1409
1410 int_sts = ulpi_read(otg, 0x87);
1411 switch (int_sts & 0x1C) {
1412 case 0x08:
1413 if (!test_and_set_bit(ID_A, &motg->inputs)) {
1414 dev_dbg(otg->dev, "ID_A\n");
1415 motg->chg_type = USB_ACA_A_CHARGER;
1416 motg->chg_state = USB_CHG_STATE_DETECTED;
1417 clear_bit(ID_B, &motg->inputs);
1418 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301419 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001420 ret = true;
1421 }
1422 break;
1423 case 0x0C:
1424 if (!test_and_set_bit(ID_B, &motg->inputs)) {
1425 dev_dbg(otg->dev, "ID_B\n");
1426 motg->chg_type = USB_ACA_B_CHARGER;
1427 motg->chg_state = USB_CHG_STATE_DETECTED;
1428 clear_bit(ID_A, &motg->inputs);
1429 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301430 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001431 ret = true;
1432 }
1433 break;
1434 case 0x10:
1435 if (!test_and_set_bit(ID_C, &motg->inputs)) {
1436 dev_dbg(otg->dev, "ID_C\n");
1437 motg->chg_type = USB_ACA_C_CHARGER;
1438 motg->chg_state = USB_CHG_STATE_DETECTED;
1439 clear_bit(ID_A, &motg->inputs);
1440 clear_bit(ID_B, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301441 set_bit(ID, &motg->inputs);
1442 ret = true;
1443 }
1444 break;
1445 case 0x04:
1446 if (test_and_clear_bit(ID, &motg->inputs)) {
1447 dev_dbg(otg->dev, "ID_GND\n");
1448 motg->chg_type = USB_INVALID_CHARGER;
1449 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1450 clear_bit(ID_A, &motg->inputs);
1451 clear_bit(ID_B, &motg->inputs);
1452 clear_bit(ID_C, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001453 ret = true;
1454 }
1455 break;
1456 default:
1457 ret = test_and_clear_bit(ID_A, &motg->inputs) |
1458 test_and_clear_bit(ID_B, &motg->inputs) |
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301459 test_and_clear_bit(ID_C, &motg->inputs) |
1460 !test_and_set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001461 if (ret) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301462 dev_dbg(otg->dev, "ID A/B/C/GND is no more\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001463 motg->chg_type = USB_INVALID_CHARGER;
1464 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1465 }
1466 }
1467out:
1468 return ret;
1469}
1470
1471static void msm_chg_enable_aca_det(struct msm_otg *motg)
1472{
1473 struct otg_transceiver *otg = &motg->otg;
1474
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301475 if (!aca_enabled())
1476 return;
1477
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001478 switch (motg->pdata->phy_type) {
1479 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301480 /* Disable ID_GND in link and PHY */
1481 writel_relaxed(readl_relaxed(USB_OTGSC) & ~(OTGSC_IDPU |
1482 OTGSC_IDIE), USB_OTGSC);
1483 ulpi_write(otg, 0x01, 0x0C);
1484 ulpi_write(otg, 0x10, 0x0F);
1485 ulpi_write(otg, 0x10, 0x12);
Pavankumar Kondeti446f4542012-02-01 13:57:13 +05301486 /* Disable PMIC ID pull-up */
1487 pm8xxx_usb_id_pullup(0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301488 /* Enable ACA ID detection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001489 ulpi_write(otg, 0x20, 0x85);
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301490 aca_id_turned_on = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001491 break;
1492 default:
1493 break;
1494 }
1495}
1496
1497static void msm_chg_enable_aca_intr(struct msm_otg *motg)
1498{
1499 struct otg_transceiver *otg = &motg->otg;
1500
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301501 if (!aca_enabled())
1502 return;
1503
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001504 switch (motg->pdata->phy_type) {
1505 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301506 /* Enable ACA Detection interrupt (on any RID change) */
1507 ulpi_write(otg, 0x01, 0x94);
1508 break;
1509 default:
1510 break;
1511 }
1512}
1513
1514static void msm_chg_disable_aca_intr(struct msm_otg *motg)
1515{
1516 struct otg_transceiver *otg = &motg->otg;
1517
1518 if (!aca_enabled())
1519 return;
1520
1521 switch (motg->pdata->phy_type) {
1522 case SNPS_28NM_INTEGRATED_PHY:
1523 ulpi_write(otg, 0x01, 0x95);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001524 break;
1525 default:
1526 break;
1527 }
1528}
1529
1530static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1531{
1532 struct otg_transceiver *otg = &motg->otg;
1533 bool ret = false;
1534
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301535 if (!aca_enabled())
1536 return ret;
1537
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001538 switch (motg->pdata->phy_type) {
1539 case SNPS_28NM_INTEGRATED_PHY:
1540 if (ulpi_read(otg, 0x91) & 1) {
1541 dev_dbg(otg->dev, "RID change\n");
1542 ulpi_write(otg, 0x01, 0x92);
1543 ret = msm_chg_aca_detect(motg);
1544 }
1545 default:
1546 break;
1547 }
1548 return ret;
1549}
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301550
1551static void msm_otg_id_timer_func(unsigned long data)
1552{
1553 struct msm_otg *motg = (struct msm_otg *) data;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301554 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301555
1556 if (!aca_enabled())
1557 return;
1558
1559 if (atomic_read(&motg->in_lpm)) {
1560 dev_dbg(motg->otg.dev, "timer: in lpm\n");
1561 return;
1562 }
1563
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301564 if (otg->state == OTG_STATE_A_SUSPEND)
1565 goto out;
1566
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301567 if (msm_chg_check_aca_intr(motg)) {
1568 dev_dbg(motg->otg.dev, "timer: aca work\n");
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301569 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301570 }
1571
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301572out:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301573 if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs))
1574 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
1575}
1576
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301577static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1578{
1579 struct otg_transceiver *otg = &motg->otg;
1580 u32 chg_det;
1581 bool ret = false;
1582
1583 switch (motg->pdata->phy_type) {
1584 case CI_45NM_INTEGRATED_PHY:
1585 chg_det = ulpi_read(otg, 0x34);
1586 ret = chg_det & (1 << 4);
1587 break;
1588 case SNPS_28NM_INTEGRATED_PHY:
1589 chg_det = ulpi_read(otg, 0x87);
1590 ret = chg_det & 1;
1591 break;
1592 default:
1593 break;
1594 }
1595 return ret;
1596}
1597
1598static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1599{
1600 struct otg_transceiver *otg = &motg->otg;
1601 u32 chg_det;
1602
1603 switch (motg->pdata->phy_type) {
1604 case CI_45NM_INTEGRATED_PHY:
1605 chg_det = ulpi_read(otg, 0x34);
1606 /* Turn off charger block */
1607 chg_det |= ~(1 << 1);
1608 ulpi_write(otg, chg_det, 0x34);
1609 udelay(20);
1610 /* control chg block via ULPI */
1611 chg_det &= ~(1 << 3);
1612 ulpi_write(otg, chg_det, 0x34);
1613 /* put it in host mode for enabling D- source */
1614 chg_det &= ~(1 << 2);
1615 ulpi_write(otg, chg_det, 0x34);
1616 /* Turn on chg detect block */
1617 chg_det &= ~(1 << 1);
1618 ulpi_write(otg, chg_det, 0x34);
1619 udelay(20);
1620 /* enable chg detection */
1621 chg_det &= ~(1 << 0);
1622 ulpi_write(otg, chg_det, 0x34);
1623 break;
1624 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondeti283146f2012-01-12 12:51:19 +05301625 /* Turn off VDP_SRC */
1626 ulpi_write(otg, 0x3, 0x86);
1627 msleep(20);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301628 /*
1629 * Configure DM as current source, DP as current sink
1630 * and enable battery charging comparators.
1631 */
1632 ulpi_write(otg, 0x8, 0x85);
1633 ulpi_write(otg, 0x2, 0x85);
1634 ulpi_write(otg, 0x1, 0x85);
1635 break;
1636 default:
1637 break;
1638 }
1639}
1640
1641static bool msm_chg_check_primary_det(struct msm_otg *motg)
1642{
1643 struct otg_transceiver *otg = &motg->otg;
1644 u32 chg_det;
1645 bool ret = false;
1646
1647 switch (motg->pdata->phy_type) {
1648 case CI_45NM_INTEGRATED_PHY:
1649 chg_det = ulpi_read(otg, 0x34);
1650 ret = chg_det & (1 << 4);
1651 break;
1652 case SNPS_28NM_INTEGRATED_PHY:
1653 chg_det = ulpi_read(otg, 0x87);
1654 ret = chg_det & 1;
1655 break;
1656 default:
1657 break;
1658 }
1659 return ret;
1660}
1661
1662static void msm_chg_enable_primary_det(struct msm_otg *motg)
1663{
1664 struct otg_transceiver *otg = &motg->otg;
1665 u32 chg_det;
1666
1667 switch (motg->pdata->phy_type) {
1668 case CI_45NM_INTEGRATED_PHY:
1669 chg_det = ulpi_read(otg, 0x34);
1670 /* enable chg detection */
1671 chg_det &= ~(1 << 0);
1672 ulpi_write(otg, chg_det, 0x34);
1673 break;
1674 case SNPS_28NM_INTEGRATED_PHY:
1675 /*
1676 * Configure DP as current source, DM as current sink
1677 * and enable battery charging comparators.
1678 */
1679 ulpi_write(otg, 0x2, 0x85);
1680 ulpi_write(otg, 0x1, 0x85);
1681 break;
1682 default:
1683 break;
1684 }
1685}
1686
1687static bool msm_chg_check_dcd(struct msm_otg *motg)
1688{
1689 struct otg_transceiver *otg = &motg->otg;
1690 u32 line_state;
1691 bool ret = false;
1692
1693 switch (motg->pdata->phy_type) {
1694 case CI_45NM_INTEGRATED_PHY:
1695 line_state = ulpi_read(otg, 0x15);
1696 ret = !(line_state & 1);
1697 break;
1698 case SNPS_28NM_INTEGRATED_PHY:
1699 line_state = ulpi_read(otg, 0x87);
1700 ret = line_state & 2;
1701 break;
1702 default:
1703 break;
1704 }
1705 return ret;
1706}
1707
1708static void msm_chg_disable_dcd(struct msm_otg *motg)
1709{
1710 struct otg_transceiver *otg = &motg->otg;
1711 u32 chg_det;
1712
1713 switch (motg->pdata->phy_type) {
1714 case CI_45NM_INTEGRATED_PHY:
1715 chg_det = ulpi_read(otg, 0x34);
1716 chg_det &= ~(1 << 5);
1717 ulpi_write(otg, chg_det, 0x34);
1718 break;
1719 case SNPS_28NM_INTEGRATED_PHY:
1720 ulpi_write(otg, 0x10, 0x86);
1721 break;
1722 default:
1723 break;
1724 }
1725}
1726
1727static void msm_chg_enable_dcd(struct msm_otg *motg)
1728{
1729 struct otg_transceiver *otg = &motg->otg;
1730 u32 chg_det;
1731
1732 switch (motg->pdata->phy_type) {
1733 case CI_45NM_INTEGRATED_PHY:
1734 chg_det = ulpi_read(otg, 0x34);
1735 /* Turn on D+ current source */
1736 chg_det |= (1 << 5);
1737 ulpi_write(otg, chg_det, 0x34);
1738 break;
1739 case SNPS_28NM_INTEGRATED_PHY:
1740 /* Data contact detection enable */
1741 ulpi_write(otg, 0x10, 0x85);
1742 break;
1743 default:
1744 break;
1745 }
1746}
1747
1748static void msm_chg_block_on(struct msm_otg *motg)
1749{
1750 struct otg_transceiver *otg = &motg->otg;
1751 u32 func_ctrl, chg_det;
1752
1753 /* put the controller in non-driving mode */
1754 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1755 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1756 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1757 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1758
1759 switch (motg->pdata->phy_type) {
1760 case CI_45NM_INTEGRATED_PHY:
1761 chg_det = ulpi_read(otg, 0x34);
1762 /* control chg block via ULPI */
1763 chg_det &= ~(1 << 3);
1764 ulpi_write(otg, chg_det, 0x34);
1765 /* Turn on chg detect block */
1766 chg_det &= ~(1 << 1);
1767 ulpi_write(otg, chg_det, 0x34);
1768 udelay(20);
1769 break;
1770 case SNPS_28NM_INTEGRATED_PHY:
1771 /* Clear charger detecting control bits */
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301772 ulpi_write(otg, 0x1F, 0x86);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301773 /* Clear alt interrupt latch and enable bits */
1774 ulpi_write(otg, 0x1F, 0x92);
1775 ulpi_write(otg, 0x1F, 0x95);
1776 udelay(100);
1777 break;
1778 default:
1779 break;
1780 }
1781}
1782
1783static void msm_chg_block_off(struct msm_otg *motg)
1784{
1785 struct otg_transceiver *otg = &motg->otg;
1786 u32 func_ctrl, chg_det;
1787
1788 switch (motg->pdata->phy_type) {
1789 case CI_45NM_INTEGRATED_PHY:
1790 chg_det = ulpi_read(otg, 0x34);
1791 /* Turn off charger block */
1792 chg_det |= ~(1 << 1);
1793 ulpi_write(otg, chg_det, 0x34);
1794 break;
1795 case SNPS_28NM_INTEGRATED_PHY:
1796 /* Clear charger detecting control bits */
1797 ulpi_write(otg, 0x3F, 0x86);
1798 /* Clear alt interrupt latch and enable bits */
1799 ulpi_write(otg, 0x1F, 0x92);
1800 ulpi_write(otg, 0x1F, 0x95);
1801 break;
1802 default:
1803 break;
1804 }
1805
1806 /* put the controller in normal mode */
1807 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1808 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1809 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1810 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1811}
1812
Anji jonnalad270e2d2011-08-09 11:28:32 +05301813static const char *chg_to_string(enum usb_chg_type chg_type)
1814{
1815 switch (chg_type) {
1816 case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
1817 case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
1818 case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
1819 case USB_ACA_A_CHARGER: return "USB_ACA_A_CHARGER";
1820 case USB_ACA_B_CHARGER: return "USB_ACA_B_CHARGER";
1821 case USB_ACA_C_CHARGER: return "USB_ACA_C_CHARGER";
1822 case USB_ACA_DOCK_CHARGER: return "USB_ACA_DOCK_CHARGER";
1823 default: return "INVALID_CHARGER";
1824 }
1825}
1826
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301827#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1828#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
Pavankumar Kondeti283146f2012-01-12 12:51:19 +05301829#define MSM_CHG_PRIMARY_DET_TIME (50 * HZ/1000) /* TVDPSRC_ON */
1830#define MSM_CHG_SECONDARY_DET_TIME (50 * HZ/1000) /* TVDMSRC_ON */
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301831static void msm_chg_detect_work(struct work_struct *w)
1832{
1833 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1834 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti2d09e5f2012-01-16 08:56:57 +05301835 bool is_dcd = false, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301836 unsigned long delay;
1837
1838 dev_dbg(otg->dev, "chg detection work\n");
1839 switch (motg->chg_state) {
1840 case USB_CHG_STATE_UNDEFINED:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301841 msm_chg_block_on(motg);
Pavankumar Kondeti2d09e5f2012-01-16 08:56:57 +05301842 if (motg->pdata->enable_dcd)
1843 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001844 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301845 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1846 motg->dcd_retries = 0;
1847 delay = MSM_CHG_DCD_POLL_TIME;
1848 break;
1849 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001850 is_aca = msm_chg_aca_detect(motg);
1851 if (is_aca) {
1852 /*
1853 * ID_A can be ACA dock too. continue
1854 * primary detection after DCD.
1855 */
1856 if (test_bit(ID_A, &motg->inputs)) {
1857 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1858 } else {
1859 delay = 0;
1860 break;
1861 }
1862 }
Pavankumar Kondeti2d09e5f2012-01-16 08:56:57 +05301863 if (motg->pdata->enable_dcd)
1864 is_dcd = msm_chg_check_dcd(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301865 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1866 if (is_dcd || tmout) {
Pavankumar Kondeti2d09e5f2012-01-16 08:56:57 +05301867 if (motg->pdata->enable_dcd)
1868 msm_chg_disable_dcd(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301869 msm_chg_enable_primary_det(motg);
1870 delay = MSM_CHG_PRIMARY_DET_TIME;
1871 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1872 } else {
1873 delay = MSM_CHG_DCD_POLL_TIME;
1874 }
1875 break;
1876 case USB_CHG_STATE_DCD_DONE:
1877 vout = msm_chg_check_primary_det(motg);
1878 if (vout) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301879 if (test_bit(ID_A, &motg->inputs)) {
1880 motg->chg_type = USB_ACA_DOCK_CHARGER;
1881 motg->chg_state = USB_CHG_STATE_DETECTED;
1882 delay = 0;
1883 break;
1884 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301885 msm_chg_enable_secondary_det(motg);
1886 delay = MSM_CHG_SECONDARY_DET_TIME;
1887 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1888 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301889 if (test_bit(ID_A, &motg->inputs)) {
1890 motg->chg_type = USB_ACA_A_CHARGER;
1891 motg->chg_state = USB_CHG_STATE_DETECTED;
1892 delay = 0;
1893 break;
1894 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301895 motg->chg_type = USB_SDP_CHARGER;
1896 motg->chg_state = USB_CHG_STATE_DETECTED;
1897 delay = 0;
1898 }
1899 break;
1900 case USB_CHG_STATE_PRIMARY_DONE:
1901 vout = msm_chg_check_secondary_det(motg);
1902 if (vout)
1903 motg->chg_type = USB_DCP_CHARGER;
1904 else
1905 motg->chg_type = USB_CDP_CHARGER;
1906 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1907 /* fall through */
1908 case USB_CHG_STATE_SECONDARY_DONE:
1909 motg->chg_state = USB_CHG_STATE_DETECTED;
1910 case USB_CHG_STATE_DETECTED:
1911 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001912 msm_chg_enable_aca_det(motg);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301913 /*
1914 * Spurious interrupt is seen after enabling ACA detection
1915 * due to which charger detection fails in case of PET.
1916 * Add delay of 100 microsec to avoid that.
1917 */
1918 udelay(100);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001919 msm_chg_enable_aca_intr(motg);
Anji jonnalad270e2d2011-08-09 11:28:32 +05301920 dev_dbg(otg->dev, "chg_type = %s\n",
1921 chg_to_string(motg->chg_type));
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301922 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301923 return;
1924 default:
1925 return;
1926 }
1927
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301928 queue_delayed_work(system_nrt_wq, &motg->chg_work, delay);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301929}
1930
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301931/*
1932 * We support OTG, Peripheral only and Host only configurations. In case
1933 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1934 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1935 * enabled when switch is controlled by user and default mode is supplied
1936 * by board file, which can be changed by userspace later.
1937 */
1938static void msm_otg_init_sm(struct msm_otg *motg)
1939{
1940 struct msm_otg_platform_data *pdata = motg->pdata;
1941 u32 otgsc = readl(USB_OTGSC);
1942
1943 switch (pdata->mode) {
1944 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001945 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301946 if (pdata->default_mode == USB_HOST) {
1947 clear_bit(ID, &motg->inputs);
1948 } else if (pdata->default_mode == USB_PERIPHERAL) {
1949 set_bit(ID, &motg->inputs);
1950 set_bit(B_SESS_VLD, &motg->inputs);
1951 } else {
1952 set_bit(ID, &motg->inputs);
1953 clear_bit(B_SESS_VLD, &motg->inputs);
1954 }
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301955 } else if (pdata->otg_control == OTG_PHY_CONTROL) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301956 if (otgsc & OTGSC_ID) {
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301957 set_bit(ID, &motg->inputs);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301958 } else {
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301959 clear_bit(ID, &motg->inputs);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05301960 set_bit(A_BUS_REQ, &motg->inputs);
1961 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001962 if (otgsc & OTGSC_BSV)
1963 set_bit(B_SESS_VLD, &motg->inputs);
1964 else
1965 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301966 } else if (pdata->otg_control == OTG_PMIC_CONTROL) {
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05301967 if (pdata->pmic_id_irq) {
Stephen Boyd431771e2012-04-18 20:00:23 -07001968 unsigned long flags;
1969 local_irq_save(flags);
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05301970 if (irq_read_line(pdata->pmic_id_irq))
1971 set_bit(ID, &motg->inputs);
1972 else
1973 clear_bit(ID, &motg->inputs);
Stephen Boyd431771e2012-04-18 20:00:23 -07001974 local_irq_restore(flags);
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05301975 }
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05301976 /*
1977 * VBUS initial state is reported after PMIC
1978 * driver initialization. Wait for it.
1979 */
1980 wait_for_completion(&pmic_vbus_init);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301981 }
1982 break;
1983 case USB_HOST:
1984 clear_bit(ID, &motg->inputs);
1985 break;
1986 case USB_PERIPHERAL:
1987 set_bit(ID, &motg->inputs);
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05301988 if (pdata->otg_control == OTG_PHY_CONTROL) {
1989 if (otgsc & OTGSC_BSV)
1990 set_bit(B_SESS_VLD, &motg->inputs);
1991 else
1992 clear_bit(B_SESS_VLD, &motg->inputs);
1993 } else if (pdata->otg_control == OTG_PMIC_CONTROL) {
1994 /*
1995 * VBUS initial state is reported after PMIC
1996 * driver initialization. Wait for it.
1997 */
1998 wait_for_completion(&pmic_vbus_init);
1999 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302000 break;
2001 default:
2002 break;
2003 }
2004}
2005
2006static void msm_otg_sm_work(struct work_struct *w)
2007{
2008 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
2009 struct otg_transceiver *otg = &motg->otg;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302010 bool work = 0, srp_reqd;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302011
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302012 pm_runtime_resume(otg->dev);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302013 pr_debug("%s work\n", otg_state_string(otg->state));
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302014 switch (otg->state) {
2015 case OTG_STATE_UNDEFINED:
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302016 msm_otg_reset(otg);
2017 msm_otg_init_sm(motg);
2018 otg->state = OTG_STATE_B_IDLE;
Pavankumar Kondeti8a379b42011-12-12 13:07:23 +05302019 if (!test_bit(B_SESS_VLD, &motg->inputs) &&
2020 test_bit(ID, &motg->inputs)) {
2021 pm_runtime_put_noidle(otg->dev);
2022 pm_runtime_suspend(otg->dev);
2023 break;
2024 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302025 /* FALL THROUGH */
2026 case OTG_STATE_B_IDLE:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002027 if ((!test_bit(ID, &motg->inputs) ||
2028 test_bit(ID_A, &motg->inputs)) && otg->host) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302029 pr_debug("!id || id_A\n");
2030 clear_bit(B_BUS_REQ, &motg->inputs);
2031 set_bit(A_BUS_REQ, &motg->inputs);
2032 otg->state = OTG_STATE_A_IDLE;
2033 work = 1;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302034 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302035 pr_debug("b_sess_vld\n");
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302036 switch (motg->chg_state) {
2037 case USB_CHG_STATE_UNDEFINED:
2038 msm_chg_detect_work(&motg->chg_work.work);
2039 break;
2040 case USB_CHG_STATE_DETECTED:
2041 switch (motg->chg_type) {
2042 case USB_DCP_CHARGER:
Pavankumar Kondeti283146f2012-01-12 12:51:19 +05302043 /* Enable VDP_SRC */
2044 ulpi_write(otg, 0x2, 0x85);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302045 msm_otg_notify_charger(motg,
2046 IDEV_CHG_MAX);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302047 pm_runtime_put_noidle(otg->dev);
2048 pm_runtime_suspend(otg->dev);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302049 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302050 case USB_ACA_B_CHARGER:
2051 msm_otg_notify_charger(motg,
2052 IDEV_ACA_CHG_MAX);
2053 /*
2054 * (ID_B --> ID_C) PHY_ALT interrupt can
2055 * not be detected in LPM.
2056 */
2057 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302058 case USB_CDP_CHARGER:
2059 msm_otg_notify_charger(motg,
2060 IDEV_CHG_MAX);
2061 msm_otg_start_peripheral(otg, 1);
2062 otg->state = OTG_STATE_B_PERIPHERAL;
2063 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302064 case USB_ACA_C_CHARGER:
2065 msm_otg_notify_charger(motg,
2066 IDEV_ACA_CHG_MAX);
2067 msm_otg_start_peripheral(otg, 1);
2068 otg->state = OTG_STATE_B_PERIPHERAL;
2069 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302070 case USB_SDP_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302071 msm_otg_start_peripheral(otg, 1);
2072 otg->state = OTG_STATE_B_PERIPHERAL;
2073 break;
2074 default:
2075 break;
2076 }
2077 break;
2078 default:
2079 break;
2080 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302081 } else if (test_bit(B_BUS_REQ, &motg->inputs)) {
2082 pr_debug("b_sess_end && b_bus_req\n");
2083 if (msm_otg_start_srp(otg) < 0) {
2084 clear_bit(B_BUS_REQ, &motg->inputs);
2085 work = 1;
2086 break;
2087 }
2088 otg->state = OTG_STATE_B_SRP_INIT;
2089 msm_otg_start_timer(motg, TB_SRP_FAIL, B_SRP_FAIL);
2090 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302091 } else {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302092 pr_debug("chg_work cancel");
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302093 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302094 motg->chg_state = USB_CHG_STATE_UNDEFINED;
2095 motg->chg_type = USB_INVALID_CHARGER;
Rajkumar Raghupathy18fd7132012-04-20 11:28:13 +05302096 msm_otg_notify_charger(motg, 0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302097 msm_otg_reset(otg);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302098 pm_runtime_put_noidle(otg->dev);
2099 pm_runtime_suspend(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302100 }
2101 break;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302102 case OTG_STATE_B_SRP_INIT:
2103 if (!test_bit(ID, &motg->inputs) ||
2104 test_bit(ID_A, &motg->inputs) ||
2105 test_bit(ID_C, &motg->inputs) ||
2106 (test_bit(B_SESS_VLD, &motg->inputs) &&
2107 !test_bit(ID_B, &motg->inputs))) {
2108 pr_debug("!id || id_a/c || b_sess_vld+!id_b\n");
2109 msm_otg_del_timer(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002110 otg->state = OTG_STATE_B_IDLE;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302111 /*
2112 * clear VBUSVLDEXTSEL and VBUSVLDEXT register
2113 * bits after SRP initiation.
2114 */
2115 ulpi_write(otg, 0x0, 0x98);
2116 work = 1;
2117 } else if (test_bit(B_SRP_FAIL, &motg->tmouts)) {
2118 pr_debug("b_srp_fail\n");
2119 pr_info("A-device did not respond to SRP\n");
2120 clear_bit(B_BUS_REQ, &motg->inputs);
2121 clear_bit(B_SRP_FAIL, &motg->tmouts);
2122 otg_send_event(OTG_EVENT_NO_RESP_FOR_SRP);
2123 ulpi_write(otg, 0x0, 0x98);
2124 otg->state = OTG_STATE_B_IDLE;
2125 motg->b_last_se0_sess = jiffies;
2126 work = 1;
2127 }
2128 break;
2129 case OTG_STATE_B_PERIPHERAL:
2130 if (!test_bit(ID, &motg->inputs) ||
2131 test_bit(ID_A, &motg->inputs) ||
2132 test_bit(ID_B, &motg->inputs) ||
2133 !test_bit(B_SESS_VLD, &motg->inputs)) {
2134 pr_debug("!id || id_a/b || !b_sess_vld\n");
Rajkumar Raghupathy18fd7132012-04-20 11:28:13 +05302135 motg->chg_state = USB_CHG_STATE_UNDEFINED;
2136 motg->chg_type = USB_INVALID_CHARGER;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302137 msm_otg_notify_charger(motg, 0);
2138 srp_reqd = otg->gadget->otg_srp_reqd;
2139 msm_otg_start_peripheral(otg, 0);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302140 if (test_bit(ID_B, &motg->inputs))
2141 clear_bit(ID_B, &motg->inputs);
2142 clear_bit(B_BUS_REQ, &motg->inputs);
2143 otg->state = OTG_STATE_B_IDLE;
2144 motg->b_last_se0_sess = jiffies;
2145 if (srp_reqd)
2146 msm_otg_start_timer(motg,
2147 TB_TST_SRP, B_TST_SRP);
2148 else
2149 work = 1;
2150 } else if (test_bit(B_BUS_REQ, &motg->inputs) &&
2151 otg->gadget->b_hnp_enable &&
2152 test_bit(A_BUS_SUSPEND, &motg->inputs)) {
2153 pr_debug("b_bus_req && b_hnp_en && a_bus_suspend\n");
2154 msm_otg_start_timer(motg, TB_ASE0_BRST, B_ASE0_BRST);
2155 /* D+ pullup should not be disconnected within 4msec
2156 * after A device suspends the bus. Otherwise PET will
2157 * fail the compliance test.
2158 */
2159 udelay(1000);
2160 msm_otg_start_peripheral(otg, 0);
2161 otg->state = OTG_STATE_B_WAIT_ACON;
2162 /*
2163 * start HCD even before A-device enable
2164 * pull-up to meet HNP timings.
2165 */
2166 otg->host->is_b_host = 1;
2167 msm_otg_start_host(otg, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002168 } else if (test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302169 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002170 }
2171 break;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302172 case OTG_STATE_B_WAIT_ACON:
2173 if (!test_bit(ID, &motg->inputs) ||
2174 test_bit(ID_A, &motg->inputs) ||
2175 test_bit(ID_B, &motg->inputs) ||
2176 !test_bit(B_SESS_VLD, &motg->inputs)) {
2177 pr_debug("!id || id_a/b || !b_sess_vld\n");
2178 msm_otg_del_timer(motg);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302179 /*
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302180 * A-device is physically disconnected during
2181 * HNP. Remove HCD.
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302182 */
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302183 msm_otg_start_host(otg, 0);
2184 otg->host->is_b_host = 0;
2185
2186 clear_bit(B_BUS_REQ, &motg->inputs);
2187 clear_bit(A_BUS_SUSPEND, &motg->inputs);
2188 motg->b_last_se0_sess = jiffies;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302189 otg->state = OTG_STATE_B_IDLE;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302190 msm_otg_reset(otg);
2191 work = 1;
2192 } else if (test_bit(A_CONN, &motg->inputs)) {
2193 pr_debug("a_conn\n");
2194 clear_bit(A_BUS_SUSPEND, &motg->inputs);
2195 otg->state = OTG_STATE_B_HOST;
2196 /*
2197 * PET disconnects D+ pullup after reset is generated
2198 * by B device in B_HOST role which is not detected by
2199 * B device. As workaorund , start timer of 300msec
2200 * and stop timer if A device is enumerated else clear
2201 * A_CONN.
2202 */
2203 msm_otg_start_timer(motg, TB_TST_CONFIG,
2204 B_TST_CONFIG);
2205 } else if (test_bit(B_ASE0_BRST, &motg->tmouts)) {
2206 pr_debug("b_ase0_brst_tmout\n");
2207 pr_info("B HNP fail:No response from A device\n");
2208 msm_otg_start_host(otg, 0);
2209 msm_otg_reset(otg);
2210 otg->host->is_b_host = 0;
2211 clear_bit(B_ASE0_BRST, &motg->tmouts);
2212 clear_bit(A_BUS_SUSPEND, &motg->inputs);
2213 clear_bit(B_BUS_REQ, &motg->inputs);
2214 otg_send_event(OTG_EVENT_HNP_FAILED);
2215 otg->state = OTG_STATE_B_IDLE;
2216 work = 1;
2217 } else if (test_bit(ID_C, &motg->inputs)) {
2218 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
2219 }
2220 break;
2221 case OTG_STATE_B_HOST:
2222 if (!test_bit(B_BUS_REQ, &motg->inputs) ||
2223 !test_bit(A_CONN, &motg->inputs) ||
2224 !test_bit(B_SESS_VLD, &motg->inputs)) {
2225 pr_debug("!b_bus_req || !a_conn || !b_sess_vld\n");
2226 clear_bit(A_CONN, &motg->inputs);
2227 clear_bit(B_BUS_REQ, &motg->inputs);
2228 msm_otg_start_host(otg, 0);
2229 otg->host->is_b_host = 0;
2230 otg->state = OTG_STATE_B_IDLE;
2231 msm_otg_reset(otg);
2232 work = 1;
2233 } else if (test_bit(ID_C, &motg->inputs)) {
2234 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
2235 }
2236 break;
2237 case OTG_STATE_A_IDLE:
2238 otg->default_a = 1;
2239 if (test_bit(ID, &motg->inputs) &&
2240 !test_bit(ID_A, &motg->inputs)) {
2241 pr_debug("id && !id_a\n");
2242 otg->default_a = 0;
2243 clear_bit(A_BUS_DROP, &motg->inputs);
2244 otg->state = OTG_STATE_B_IDLE;
2245 del_timer_sync(&motg->id_timer);
2246 msm_otg_link_reset(motg);
2247 msm_chg_enable_aca_intr(motg);
2248 msm_otg_notify_charger(motg, 0);
2249 work = 1;
2250 } else if (!test_bit(A_BUS_DROP, &motg->inputs) &&
2251 (test_bit(A_SRP_DET, &motg->inputs) ||
2252 test_bit(A_BUS_REQ, &motg->inputs))) {
2253 pr_debug("!a_bus_drop && (a_srp_det || a_bus_req)\n");
2254
2255 clear_bit(A_SRP_DET, &motg->inputs);
2256 /* Disable SRP detection */
2257 writel_relaxed((readl_relaxed(USB_OTGSC) &
2258 ~OTGSC_INTSTS_MASK) &
2259 ~OTGSC_DPIE, USB_OTGSC);
2260
2261 otg->state = OTG_STATE_A_WAIT_VRISE;
2262 /* VBUS should not be supplied before end of SRP pulse
2263 * generated by PET, if not complaince test fail.
2264 */
2265 usleep_range(10000, 12000);
2266 /* ACA: ID_A: Stop charging untill enumeration */
2267 if (test_bit(ID_A, &motg->inputs))
2268 msm_otg_notify_charger(motg, 0);
2269 else
2270 msm_hsusb_vbus_power(motg, 1);
2271 msm_otg_start_timer(motg, TA_WAIT_VRISE, A_WAIT_VRISE);
2272 } else {
2273 pr_debug("No session requested\n");
2274 clear_bit(A_BUS_DROP, &motg->inputs);
2275 if (test_bit(ID_A, &motg->inputs)) {
2276 msm_otg_notify_charger(motg,
2277 IDEV_ACA_CHG_MAX);
2278 } else if (!test_bit(ID, &motg->inputs)) {
2279 msm_otg_notify_charger(motg, 0);
2280 /*
2281 * A-device is not providing power on VBUS.
2282 * Enable SRP detection.
2283 */
2284 writel_relaxed(0x13, USB_USBMODE);
2285 writel_relaxed((readl_relaxed(USB_OTGSC) &
2286 ~OTGSC_INTSTS_MASK) |
2287 OTGSC_DPIE, USB_OTGSC);
2288 mb();
2289 }
2290 }
2291 break;
2292 case OTG_STATE_A_WAIT_VRISE:
2293 if ((test_bit(ID, &motg->inputs) &&
2294 !test_bit(ID_A, &motg->inputs)) ||
2295 test_bit(A_BUS_DROP, &motg->inputs) ||
2296 test_bit(A_WAIT_VRISE, &motg->tmouts)) {
2297 pr_debug("id || a_bus_drop || a_wait_vrise_tmout\n");
2298 clear_bit(A_BUS_REQ, &motg->inputs);
2299 msm_otg_del_timer(motg);
2300 msm_hsusb_vbus_power(motg, 0);
2301 otg->state = OTG_STATE_A_WAIT_VFALL;
2302 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2303 } else if (test_bit(A_VBUS_VLD, &motg->inputs)) {
2304 pr_debug("a_vbus_vld\n");
2305 otg->state = OTG_STATE_A_WAIT_BCON;
2306 if (TA_WAIT_BCON > 0)
2307 msm_otg_start_timer(motg, TA_WAIT_BCON,
2308 A_WAIT_BCON);
2309 msm_otg_start_host(otg, 1);
2310 msm_chg_enable_aca_det(motg);
2311 msm_chg_disable_aca_intr(motg);
Chiranjeevi Velempati489a27c2012-03-29 09:47:17 +05302312 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302313 if (msm_chg_check_aca_intr(motg))
2314 work = 1;
2315 }
2316 break;
2317 case OTG_STATE_A_WAIT_BCON:
2318 if ((test_bit(ID, &motg->inputs) &&
2319 !test_bit(ID_A, &motg->inputs)) ||
2320 test_bit(A_BUS_DROP, &motg->inputs) ||
2321 test_bit(A_WAIT_BCON, &motg->tmouts)) {
2322 pr_debug("(id && id_a/b/c) || a_bus_drop ||"
2323 "a_wait_bcon_tmout\n");
2324 if (test_bit(A_WAIT_BCON, &motg->tmouts)) {
2325 pr_info("Device No Response\n");
2326 otg_send_event(OTG_EVENT_DEV_CONN_TMOUT);
2327 }
2328 msm_otg_del_timer(motg);
2329 clear_bit(A_BUS_REQ, &motg->inputs);
2330 clear_bit(B_CONN, &motg->inputs);
2331 msm_otg_start_host(otg, 0);
2332 /*
2333 * ACA: ID_A with NO accessory, just the A plug is
2334 * attached to ACA: Use IDCHG_MAX for charging
2335 */
2336 if (test_bit(ID_A, &motg->inputs))
2337 msm_otg_notify_charger(motg, IDEV_CHG_MIN);
2338 else
2339 msm_hsusb_vbus_power(motg, 0);
2340 otg->state = OTG_STATE_A_WAIT_VFALL;
2341 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2342 } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
2343 pr_debug("!a_vbus_vld\n");
2344 clear_bit(B_CONN, &motg->inputs);
2345 msm_otg_del_timer(motg);
2346 msm_otg_start_host(otg, 0);
2347 otg->state = OTG_STATE_A_VBUS_ERR;
2348 msm_otg_reset(otg);
2349 } else if (test_bit(ID_A, &motg->inputs)) {
2350 msm_hsusb_vbus_power(motg, 0);
2351 } else if (!test_bit(A_BUS_REQ, &motg->inputs)) {
2352 /*
2353 * If TA_WAIT_BCON is infinite, we don;t
2354 * turn off VBUS. Enter low power mode.
2355 */
2356 if (TA_WAIT_BCON < 0)
2357 pm_runtime_put_sync(otg->dev);
2358 } else if (!test_bit(ID, &motg->inputs)) {
2359 msm_hsusb_vbus_power(motg, 1);
2360 }
2361 break;
2362 case OTG_STATE_A_HOST:
2363 if ((test_bit(ID, &motg->inputs) &&
2364 !test_bit(ID_A, &motg->inputs)) ||
2365 test_bit(A_BUS_DROP, &motg->inputs)) {
2366 pr_debug("id_a/b/c || a_bus_drop\n");
2367 clear_bit(B_CONN, &motg->inputs);
2368 clear_bit(A_BUS_REQ, &motg->inputs);
2369 msm_otg_del_timer(motg);
2370 otg->state = OTG_STATE_A_WAIT_VFALL;
2371 msm_otg_start_host(otg, 0);
2372 if (!test_bit(ID_A, &motg->inputs))
2373 msm_hsusb_vbus_power(motg, 0);
2374 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2375 } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
2376 pr_debug("!a_vbus_vld\n");
2377 clear_bit(B_CONN, &motg->inputs);
2378 msm_otg_del_timer(motg);
2379 otg->state = OTG_STATE_A_VBUS_ERR;
2380 msm_otg_start_host(otg, 0);
2381 msm_otg_reset(otg);
2382 } else if (!test_bit(A_BUS_REQ, &motg->inputs)) {
2383 /*
2384 * a_bus_req is de-asserted when root hub is
2385 * suspended or HNP is in progress.
2386 */
2387 pr_debug("!a_bus_req\n");
2388 msm_otg_del_timer(motg);
2389 otg->state = OTG_STATE_A_SUSPEND;
2390 if (otg->host->b_hnp_enable)
2391 msm_otg_start_timer(motg, TA_AIDL_BDIS,
2392 A_AIDL_BDIS);
2393 else
2394 pm_runtime_put_sync(otg->dev);
2395 } else if (!test_bit(B_CONN, &motg->inputs)) {
2396 pr_debug("!b_conn\n");
2397 msm_otg_del_timer(motg);
2398 otg->state = OTG_STATE_A_WAIT_BCON;
2399 if (TA_WAIT_BCON > 0)
2400 msm_otg_start_timer(motg, TA_WAIT_BCON,
2401 A_WAIT_BCON);
2402 if (msm_chg_check_aca_intr(motg))
2403 work = 1;
2404 } else if (test_bit(ID_A, &motg->inputs)) {
2405 msm_otg_del_timer(motg);
2406 msm_hsusb_vbus_power(motg, 0);
2407 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
2408 msm_otg_notify_charger(motg,
2409 IDEV_ACA_CHG_MAX);
2410 else
2411 msm_otg_notify_charger(motg,
2412 IDEV_CHG_MIN - motg->mA_port);
2413 } else if (!test_bit(ID, &motg->inputs)) {
2414 motg->chg_state = USB_CHG_STATE_UNDEFINED;
2415 motg->chg_type = USB_INVALID_CHARGER;
2416 msm_otg_notify_charger(motg, 0);
2417 msm_hsusb_vbus_power(motg, 1);
2418 }
2419 break;
2420 case OTG_STATE_A_SUSPEND:
2421 if ((test_bit(ID, &motg->inputs) &&
2422 !test_bit(ID_A, &motg->inputs)) ||
2423 test_bit(A_BUS_DROP, &motg->inputs) ||
2424 test_bit(A_AIDL_BDIS, &motg->tmouts)) {
2425 pr_debug("id_a/b/c || a_bus_drop ||"
2426 "a_aidl_bdis_tmout\n");
2427 msm_otg_del_timer(motg);
2428 clear_bit(B_CONN, &motg->inputs);
2429 otg->state = OTG_STATE_A_WAIT_VFALL;
2430 msm_otg_start_host(otg, 0);
2431 msm_otg_reset(otg);
2432 if (!test_bit(ID_A, &motg->inputs))
2433 msm_hsusb_vbus_power(motg, 0);
2434 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2435 } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
2436 pr_debug("!a_vbus_vld\n");
2437 msm_otg_del_timer(motg);
2438 clear_bit(B_CONN, &motg->inputs);
2439 otg->state = OTG_STATE_A_VBUS_ERR;
2440 msm_otg_start_host(otg, 0);
2441 msm_otg_reset(otg);
2442 } else if (!test_bit(B_CONN, &motg->inputs) &&
2443 otg->host->b_hnp_enable) {
2444 pr_debug("!b_conn && b_hnp_enable");
2445 otg->state = OTG_STATE_A_PERIPHERAL;
2446 msm_otg_host_hnp_enable(otg, 1);
2447 otg->gadget->is_a_peripheral = 1;
2448 msm_otg_start_peripheral(otg, 1);
2449 } else if (!test_bit(B_CONN, &motg->inputs) &&
2450 !otg->host->b_hnp_enable) {
2451 pr_debug("!b_conn && !b_hnp_enable");
2452 /*
2453 * bus request is dropped during suspend.
2454 * acquire again for next device.
2455 */
2456 set_bit(A_BUS_REQ, &motg->inputs);
2457 otg->state = OTG_STATE_A_WAIT_BCON;
2458 if (TA_WAIT_BCON > 0)
2459 msm_otg_start_timer(motg, TA_WAIT_BCON,
2460 A_WAIT_BCON);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002461 } else if (test_bit(ID_A, &motg->inputs)) {
Mayank Ranae3926882011-12-26 09:47:54 +05302462 msm_hsusb_vbus_power(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002463 msm_otg_notify_charger(motg,
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302464 IDEV_CHG_MIN - motg->mA_port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002465 } else if (!test_bit(ID, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002466 msm_otg_notify_charger(motg, 0);
Mayank Ranae3926882011-12-26 09:47:54 +05302467 msm_hsusb_vbus_power(motg, 1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302468 }
2469 break;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302470 case OTG_STATE_A_PERIPHERAL:
2471 if ((test_bit(ID, &motg->inputs) &&
2472 !test_bit(ID_A, &motg->inputs)) ||
2473 test_bit(A_BUS_DROP, &motg->inputs)) {
2474 pr_debug("id _f/b/c || a_bus_drop\n");
2475 /* Clear BIDL_ADIS timer */
2476 msm_otg_del_timer(motg);
2477 otg->state = OTG_STATE_A_WAIT_VFALL;
2478 msm_otg_start_peripheral(otg, 0);
2479 otg->gadget->is_a_peripheral = 0;
2480 msm_otg_start_host(otg, 0);
2481 msm_otg_reset(otg);
2482 if (!test_bit(ID_A, &motg->inputs))
2483 msm_hsusb_vbus_power(motg, 0);
2484 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2485 } else if (!test_bit(A_VBUS_VLD, &motg->inputs)) {
2486 pr_debug("!a_vbus_vld\n");
2487 /* Clear BIDL_ADIS timer */
2488 msm_otg_del_timer(motg);
2489 otg->state = OTG_STATE_A_VBUS_ERR;
2490 msm_otg_start_peripheral(otg, 0);
2491 otg->gadget->is_a_peripheral = 0;
2492 msm_otg_start_host(otg, 0);
2493 } else if (test_bit(A_BIDL_ADIS, &motg->tmouts)) {
2494 pr_debug("a_bidl_adis_tmout\n");
2495 msm_otg_start_peripheral(otg, 0);
2496 otg->gadget->is_a_peripheral = 0;
2497 otg->state = OTG_STATE_A_WAIT_BCON;
2498 set_bit(A_BUS_REQ, &motg->inputs);
2499 msm_otg_host_hnp_enable(otg, 0);
2500 if (TA_WAIT_BCON > 0)
2501 msm_otg_start_timer(motg, TA_WAIT_BCON,
2502 A_WAIT_BCON);
2503 } else if (test_bit(ID_A, &motg->inputs)) {
2504 msm_hsusb_vbus_power(motg, 0);
2505 msm_otg_notify_charger(motg,
2506 IDEV_CHG_MIN - motg->mA_port);
2507 } else if (!test_bit(ID, &motg->inputs)) {
2508 msm_otg_notify_charger(motg, 0);
2509 msm_hsusb_vbus_power(motg, 1);
2510 }
2511 break;
2512 case OTG_STATE_A_WAIT_VFALL:
2513 if (test_bit(A_WAIT_VFALL, &motg->tmouts)) {
2514 clear_bit(A_VBUS_VLD, &motg->inputs);
2515 otg->state = OTG_STATE_A_IDLE;
2516 work = 1;
2517 }
2518 break;
2519 case OTG_STATE_A_VBUS_ERR:
2520 if ((test_bit(ID, &motg->inputs) &&
2521 !test_bit(ID_A, &motg->inputs)) ||
2522 test_bit(A_BUS_DROP, &motg->inputs) ||
2523 test_bit(A_CLR_ERR, &motg->inputs)) {
2524 otg->state = OTG_STATE_A_WAIT_VFALL;
2525 if (!test_bit(ID_A, &motg->inputs))
2526 msm_hsusb_vbus_power(motg, 0);
2527 msm_otg_start_timer(motg, TA_WAIT_VFALL, A_WAIT_VFALL);
2528 motg->chg_state = USB_CHG_STATE_UNDEFINED;
2529 motg->chg_type = USB_INVALID_CHARGER;
2530 msm_otg_notify_charger(motg, 0);
2531 }
2532 break;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302533 default:
2534 break;
2535 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302536 if (work)
2537 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302538}
2539
2540static irqreturn_t msm_otg_irq(int irq, void *data)
2541{
2542 struct msm_otg *motg = data;
2543 struct otg_transceiver *otg = &motg->otg;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302544 u32 otgsc = 0, usbsts, pc;
2545 bool work = 0;
2546 irqreturn_t ret = IRQ_HANDLED;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302547
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302548 if (atomic_read(&motg->in_lpm)) {
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302549 pr_debug("OTG IRQ: in LPM\n");
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302550 disable_irq_nosync(irq);
2551 motg->async_int = 1;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302552 pm_request_resume(otg->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302553 return IRQ_HANDLED;
2554 }
2555
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002556 usbsts = readl(USB_USBSTS);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302557 otgsc = readl(USB_OTGSC);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302558
2559 if (!(otgsc & OTG_OTGSTS_MASK) && !(usbsts & OTG_USBSTS_MASK))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302560 return IRQ_NONE;
2561
2562 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302563 if (otgsc & OTGSC_ID) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302564 pr_debug("Id set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302565 set_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302566 } else {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302567 pr_debug("Id clear\n");
2568 /*
2569 * Assert a_bus_req to supply power on
2570 * VBUS when Micro/Mini-A cable is connected
2571 * with out user intervention.
2572 */
2573 set_bit(A_BUS_REQ, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302574 clear_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302575 msm_chg_enable_aca_det(motg);
2576 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302577 writel_relaxed(otgsc, USB_OTGSC);
2578 work = 1;
2579 } else if (otgsc & OTGSC_DPIS) {
2580 pr_debug("DPIS detected\n");
2581 writel_relaxed(otgsc, USB_OTGSC);
2582 set_bit(A_SRP_DET, &motg->inputs);
2583 set_bit(A_BUS_REQ, &motg->inputs);
2584 work = 1;
2585 } else if (otgsc & OTGSC_BSVIS) {
2586 writel_relaxed(otgsc, USB_OTGSC);
2587 /*
2588 * BSV interrupt comes when operating as an A-device
2589 * (VBUS on/off).
2590 * But, handle BSV when charger is removed from ACA in ID_A
2591 */
2592 if ((otg->state >= OTG_STATE_A_IDLE) &&
2593 !test_bit(ID_A, &motg->inputs))
2594 return IRQ_HANDLED;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302595 if (otgsc & OTGSC_BSV) {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302596 pr_debug("BSV set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302597 set_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302598 } else {
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302599 pr_debug("BSV clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302600 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302601 msm_chg_check_aca_intr(motg);
2602 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302603 work = 1;
2604 } else if (usbsts & STS_PCI) {
2605 pc = readl_relaxed(USB_PORTSC);
2606 pr_debug("portsc = %x\n", pc);
2607 ret = IRQ_NONE;
2608 /*
2609 * HCD Acks PCI interrupt. We use this to switch
2610 * between different OTG states.
2611 */
2612 work = 1;
2613 switch (otg->state) {
2614 case OTG_STATE_A_SUSPEND:
2615 if (otg->host->b_hnp_enable && (pc & PORTSC_CSC) &&
2616 !(pc & PORTSC_CCS)) {
2617 pr_debug("B_CONN clear\n");
2618 clear_bit(B_CONN, &motg->inputs);
2619 msm_otg_del_timer(motg);
2620 }
2621 break;
2622 case OTG_STATE_A_PERIPHERAL:
2623 /*
2624 * A-peripheral observed activity on bus.
2625 * clear A_BIDL_ADIS timer.
2626 */
2627 msm_otg_del_timer(motg);
2628 work = 0;
2629 break;
2630 case OTG_STATE_B_WAIT_ACON:
2631 if ((pc & PORTSC_CSC) && (pc & PORTSC_CCS)) {
2632 pr_debug("A_CONN set\n");
2633 set_bit(A_CONN, &motg->inputs);
2634 /* Clear ASE0_BRST timer */
2635 msm_otg_del_timer(motg);
2636 }
2637 break;
2638 case OTG_STATE_B_HOST:
2639 if ((pc & PORTSC_CSC) && !(pc & PORTSC_CCS)) {
2640 pr_debug("A_CONN clear\n");
2641 clear_bit(A_CONN, &motg->inputs);
2642 msm_otg_del_timer(motg);
2643 }
2644 break;
2645 case OTG_STATE_A_WAIT_BCON:
2646 if (TA_WAIT_BCON < 0)
2647 set_bit(A_BUS_REQ, &motg->inputs);
2648 default:
2649 work = 0;
2650 break;
2651 }
2652 } else if (usbsts & STS_URI) {
2653 ret = IRQ_NONE;
2654 switch (otg->state) {
2655 case OTG_STATE_A_PERIPHERAL:
2656 /*
2657 * A-peripheral observed activity on bus.
2658 * clear A_BIDL_ADIS timer.
2659 */
2660 msm_otg_del_timer(motg);
2661 work = 0;
2662 break;
2663 default:
2664 work = 0;
2665 break;
2666 }
2667 } else if (usbsts & STS_SLI) {
2668 ret = IRQ_NONE;
2669 work = 0;
2670 switch (otg->state) {
2671 case OTG_STATE_B_PERIPHERAL:
2672 if (otg->gadget->b_hnp_enable) {
2673 set_bit(A_BUS_SUSPEND, &motg->inputs);
2674 set_bit(B_BUS_REQ, &motg->inputs);
2675 work = 1;
2676 }
2677 break;
2678 case OTG_STATE_A_PERIPHERAL:
2679 msm_otg_start_timer(motg, TA_BIDL_ADIS,
2680 A_BIDL_ADIS);
2681 break;
2682 default:
2683 break;
2684 }
2685 } else if ((usbsts & PHY_ALT_INT)) {
2686 writel_relaxed(PHY_ALT_INT, USB_USBSTS);
2687 if (msm_chg_check_aca_intr(motg))
2688 work = 1;
2689 ret = IRQ_HANDLED;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302690 }
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302691 if (work)
2692 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302693
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302694 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002695}
2696
2697static void msm_otg_set_vbus_state(int online)
2698{
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302699 static bool init;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002700 struct msm_otg *motg = the_msm_otg;
2701
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302702 if (online) {
2703 pr_debug("PMIC: BSV set\n");
2704 set_bit(B_SESS_VLD, &motg->inputs);
2705 } else {
2706 pr_debug("PMIC: BSV clear\n");
2707 clear_bit(B_SESS_VLD, &motg->inputs);
2708 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002709
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302710 if (!init) {
2711 init = true;
2712 complete(&pmic_vbus_init);
2713 pr_debug("PMIC: BSV init complete\n");
2714 return;
2715 }
2716
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302717 queue_work(system_nrt_wq, &motg->sm_work);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002718}
2719
2720static irqreturn_t msm_pmic_id_irq(int irq, void *data)
2721{
2722 struct msm_otg *motg = data;
2723
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302724 if (aca_id_turned_on)
2725 return IRQ_HANDLED;
2726
2727 if (irq_read_line(motg->pdata->pmic_id_irq)) {
2728 pr_debug("PMIC: ID set\n");
2729 set_bit(ID, &motg->inputs);
2730 } else {
2731 pr_debug("PMIC: ID clear\n");
2732 clear_bit(ID, &motg->inputs);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302733 set_bit(A_BUS_REQ, &motg->inputs);
Pavankumar Kondeti4960f312011-12-06 15:46:14 +05302734 }
2735
2736 if (motg->otg.state != OTG_STATE_UNDEFINED)
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302737 queue_work(system_nrt_wq, &motg->sm_work);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002738
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302739 return IRQ_HANDLED;
2740}
2741
2742static int msm_otg_mode_show(struct seq_file *s, void *unused)
2743{
2744 struct msm_otg *motg = s->private;
2745 struct otg_transceiver *otg = &motg->otg;
2746
2747 switch (otg->state) {
2748 case OTG_STATE_A_HOST:
2749 seq_printf(s, "host\n");
2750 break;
2751 case OTG_STATE_B_PERIPHERAL:
2752 seq_printf(s, "peripheral\n");
2753 break;
2754 default:
2755 seq_printf(s, "none\n");
2756 break;
2757 }
2758
2759 return 0;
2760}
2761
2762static int msm_otg_mode_open(struct inode *inode, struct file *file)
2763{
2764 return single_open(file, msm_otg_mode_show, inode->i_private);
2765}
2766
2767static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
2768 size_t count, loff_t *ppos)
2769{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05302770 struct seq_file *s = file->private_data;
2771 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302772 char buf[16];
2773 struct otg_transceiver *otg = &motg->otg;
2774 int status = count;
2775 enum usb_mode_type req_mode;
2776
2777 memset(buf, 0x00, sizeof(buf));
2778
2779 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
2780 status = -EFAULT;
2781 goto out;
2782 }
2783
2784 if (!strncmp(buf, "host", 4)) {
2785 req_mode = USB_HOST;
2786 } else if (!strncmp(buf, "peripheral", 10)) {
2787 req_mode = USB_PERIPHERAL;
2788 } else if (!strncmp(buf, "none", 4)) {
2789 req_mode = USB_NONE;
2790 } else {
2791 status = -EINVAL;
2792 goto out;
2793 }
2794
2795 switch (req_mode) {
2796 case USB_NONE:
2797 switch (otg->state) {
2798 case OTG_STATE_A_HOST:
2799 case OTG_STATE_B_PERIPHERAL:
2800 set_bit(ID, &motg->inputs);
2801 clear_bit(B_SESS_VLD, &motg->inputs);
2802 break;
2803 default:
2804 goto out;
2805 }
2806 break;
2807 case USB_PERIPHERAL:
2808 switch (otg->state) {
2809 case OTG_STATE_B_IDLE:
2810 case OTG_STATE_A_HOST:
2811 set_bit(ID, &motg->inputs);
2812 set_bit(B_SESS_VLD, &motg->inputs);
2813 break;
2814 default:
2815 goto out;
2816 }
2817 break;
2818 case USB_HOST:
2819 switch (otg->state) {
2820 case OTG_STATE_B_IDLE:
2821 case OTG_STATE_B_PERIPHERAL:
2822 clear_bit(ID, &motg->inputs);
2823 break;
2824 default:
2825 goto out;
2826 }
2827 break;
2828 default:
2829 goto out;
2830 }
2831
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302832 pm_runtime_resume(otg->dev);
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05302833 queue_work(system_nrt_wq, &motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302834out:
2835 return status;
2836}
2837
2838const struct file_operations msm_otg_mode_fops = {
2839 .open = msm_otg_mode_open,
2840 .read = seq_read,
2841 .write = msm_otg_mode_write,
2842 .llseek = seq_lseek,
2843 .release = single_release,
2844};
2845
Chiranjeevi Velempatif9a11542012-03-28 18:18:34 +05302846static int msm_otg_show_otg_state(struct seq_file *s, void *unused)
2847{
2848 struct msm_otg *motg = s->private;
2849 struct otg_transceiver *otg = &motg->otg;
2850
2851 seq_printf(s, "%s\n", otg_state_string(otg->state));
2852 return 0;
2853}
2854
2855static int msm_otg_otg_state_open(struct inode *inode, struct file *file)
2856{
2857 return single_open(file, msm_otg_show_otg_state, inode->i_private);
2858}
2859
2860const struct file_operations msm_otg_state_fops = {
2861 .open = msm_otg_otg_state_open,
2862 .read = seq_read,
2863 .llseek = seq_lseek,
2864 .release = single_release,
2865};
2866
Anji jonnalad270e2d2011-08-09 11:28:32 +05302867static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
2868{
2869 struct msm_otg *motg = s->private;
2870
Pavankumar Kondeti9ef69cb2011-12-12 14:18:22 +05302871 seq_printf(s, "%s\n", chg_to_string(motg->chg_type));
Anji jonnalad270e2d2011-08-09 11:28:32 +05302872 return 0;
2873}
2874
2875static int msm_otg_chg_open(struct inode *inode, struct file *file)
2876{
2877 return single_open(file, msm_otg_show_chg_type, inode->i_private);
2878}
2879
2880const struct file_operations msm_otg_chg_fops = {
2881 .open = msm_otg_chg_open,
2882 .read = seq_read,
2883 .llseek = seq_lseek,
2884 .release = single_release,
2885};
2886
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302887static int msm_otg_aca_show(struct seq_file *s, void *unused)
2888{
2889 if (debug_aca_enabled)
2890 seq_printf(s, "enabled\n");
2891 else
2892 seq_printf(s, "disabled\n");
2893
2894 return 0;
2895}
2896
2897static int msm_otg_aca_open(struct inode *inode, struct file *file)
2898{
2899 return single_open(file, msm_otg_aca_show, inode->i_private);
2900}
2901
2902static ssize_t msm_otg_aca_write(struct file *file, const char __user *ubuf,
2903 size_t count, loff_t *ppos)
2904{
2905 char buf[8];
2906
2907 memset(buf, 0x00, sizeof(buf));
2908
2909 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
2910 return -EFAULT;
2911
2912 if (!strncmp(buf, "enable", 6))
2913 debug_aca_enabled = true;
2914 else
2915 debug_aca_enabled = false;
2916
2917 return count;
2918}
2919
2920const struct file_operations msm_otg_aca_fops = {
2921 .open = msm_otg_aca_open,
2922 .read = seq_read,
2923 .write = msm_otg_aca_write,
2924 .llseek = seq_lseek,
2925 .release = single_release,
2926};
2927
Manu Gautam8bdcc592012-03-06 11:26:06 +05302928static int msm_otg_bus_show(struct seq_file *s, void *unused)
2929{
2930 if (debug_bus_voting_enabled)
2931 seq_printf(s, "enabled\n");
2932 else
2933 seq_printf(s, "disabled\n");
2934
2935 return 0;
2936}
2937
2938static int msm_otg_bus_open(struct inode *inode, struct file *file)
2939{
2940 return single_open(file, msm_otg_bus_show, inode->i_private);
2941}
2942
2943static ssize_t msm_otg_bus_write(struct file *file, const char __user *ubuf,
2944 size_t count, loff_t *ppos)
2945{
2946 char buf[8];
2947 int ret;
2948 struct seq_file *s = file->private_data;
2949 struct msm_otg *motg = s->private;
2950
2951 memset(buf, 0x00, sizeof(buf));
2952
2953 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
2954 return -EFAULT;
2955
2956 if (!strncmp(buf, "enable", 6)) {
2957 /* Do not vote here. Let OTG statemachine decide when to vote */
2958 debug_bus_voting_enabled = true;
2959 } else {
2960 debug_bus_voting_enabled = false;
2961 if (motg->bus_perf_client) {
2962 ret = msm_bus_scale_client_update_request(
2963 motg->bus_perf_client, 0);
2964 if (ret)
2965 dev_err(motg->otg.dev, "%s: Failed to devote "
2966 "for bus bw %d\n", __func__, ret);
2967 }
2968 }
2969
2970 return count;
2971}
2972
2973const struct file_operations msm_otg_bus_fops = {
2974 .open = msm_otg_bus_open,
2975 .read = seq_read,
2976 .write = msm_otg_bus_write,
2977 .llseek = seq_lseek,
2978 .release = single_release,
2979};
2980
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302981static struct dentry *msm_otg_dbg_root;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302982
2983static int msm_otg_debugfs_init(struct msm_otg *motg)
2984{
Manu Gautam8bdcc592012-03-06 11:26:06 +05302985 struct dentry *msm_otg_dentry;
Anji jonnalad270e2d2011-08-09 11:28:32 +05302986
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302987 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
2988
2989 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
2990 return -ENODEV;
2991
Anji jonnalad270e2d2011-08-09 11:28:32 +05302992 if (motg->pdata->mode == USB_OTG &&
2993 motg->pdata->otg_control == OTG_USER_CONTROL) {
2994
Manu Gautam8bdcc592012-03-06 11:26:06 +05302995 msm_otg_dentry = debugfs_create_file("mode", S_IRUGO |
Anji jonnalad270e2d2011-08-09 11:28:32 +05302996 S_IWUSR, msm_otg_dbg_root, motg,
2997 &msm_otg_mode_fops);
2998
Manu Gautam8bdcc592012-03-06 11:26:06 +05302999 if (!msm_otg_dentry) {
Anji jonnalad270e2d2011-08-09 11:28:32 +05303000 debugfs_remove(msm_otg_dbg_root);
3001 msm_otg_dbg_root = NULL;
3002 return -ENODEV;
3003 }
3004 }
3005
Manu Gautam8bdcc592012-03-06 11:26:06 +05303006 msm_otg_dentry = debugfs_create_file("chg_type", S_IRUGO,
Anji jonnalad270e2d2011-08-09 11:28:32 +05303007 msm_otg_dbg_root, motg,
3008 &msm_otg_chg_fops);
3009
Manu Gautam8bdcc592012-03-06 11:26:06 +05303010 if (!msm_otg_dentry) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303011 debugfs_remove_recursive(msm_otg_dbg_root);
3012 return -ENODEV;
3013 }
3014
Manu Gautam8bdcc592012-03-06 11:26:06 +05303015 msm_otg_dentry = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303016 msm_otg_dbg_root, motg,
3017 &msm_otg_aca_fops);
3018
Manu Gautam8bdcc592012-03-06 11:26:06 +05303019 if (!msm_otg_dentry) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303020 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303021 return -ENODEV;
3022 }
3023
Manu Gautam8bdcc592012-03-06 11:26:06 +05303024 msm_otg_dentry = debugfs_create_file("bus_voting", S_IRUGO | S_IWUSR,
3025 msm_otg_dbg_root, motg,
3026 &msm_otg_bus_fops);
3027
3028 if (!msm_otg_dentry) {
3029 debugfs_remove_recursive(msm_otg_dbg_root);
3030 return -ENODEV;
3031 }
Chiranjeevi Velempatif9a11542012-03-28 18:18:34 +05303032
3033 msm_otg_dentry = debugfs_create_file("otg_state", S_IRUGO,
3034 msm_otg_dbg_root, motg, &msm_otg_state_fops);
3035
3036 if (!msm_otg_dentry) {
3037 debugfs_remove_recursive(msm_otg_dbg_root);
3038 return -ENODEV;
3039 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303040 return 0;
3041}
3042
3043static void msm_otg_debugfs_cleanup(void)
3044{
Anji jonnalad270e2d2011-08-09 11:28:32 +05303045 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303046}
3047
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303048static u64 msm_otg_dma_mask = DMA_BIT_MASK(64);
3049static struct platform_device *msm_otg_add_pdev(
3050 struct platform_device *ofdev, const char *name)
3051{
3052 struct platform_device *pdev;
3053 const struct resource *res = ofdev->resource;
3054 unsigned int num = ofdev->num_resources;
3055 int retval;
3056
3057 pdev = platform_device_alloc(name, -1);
3058 if (!pdev) {
3059 retval = -ENOMEM;
3060 goto error;
3061 }
3062
3063 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
3064 pdev->dev.dma_mask = &msm_otg_dma_mask;
3065
3066 if (num) {
3067 retval = platform_device_add_resources(pdev, res, num);
3068 if (retval)
3069 goto error;
3070 }
3071
3072 retval = platform_device_add(pdev);
3073 if (retval)
3074 goto error;
3075
3076 return pdev;
3077
3078error:
3079 platform_device_put(pdev);
3080 return ERR_PTR(retval);
3081}
3082
3083static int msm_otg_setup_devices(struct platform_device *ofdev,
3084 enum usb_mode_type mode, bool init)
3085{
3086 const char *gadget_name = "msm_hsusb";
3087 const char *host_name = "msm_hsusb_host";
3088 static struct platform_device *gadget_pdev;
3089 static struct platform_device *host_pdev;
3090 int retval = 0;
3091
3092 if (!init) {
3093 if (gadget_pdev)
3094 platform_device_unregister(gadget_pdev);
3095 if (host_pdev)
3096 platform_device_unregister(host_pdev);
3097 return 0;
3098 }
3099
3100 switch (mode) {
3101 case USB_OTG:
3102 /* fall through */
3103 case USB_PERIPHERAL:
3104 gadget_pdev = msm_otg_add_pdev(ofdev, gadget_name);
3105 if (IS_ERR(gadget_pdev)) {
3106 retval = PTR_ERR(gadget_pdev);
3107 break;
3108 }
3109 if (mode == USB_PERIPHERAL)
3110 break;
3111 /* fall through */
3112 case USB_HOST:
3113 host_pdev = msm_otg_add_pdev(ofdev, host_name);
3114 if (IS_ERR(host_pdev)) {
3115 retval = PTR_ERR(host_pdev);
3116 if (mode == USB_OTG)
3117 platform_device_unregister(gadget_pdev);
3118 }
3119 break;
3120 default:
3121 break;
3122 }
3123
3124 return retval;
3125}
3126
3127struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
3128{
3129 struct device_node *node = pdev->dev.of_node;
3130 struct msm_otg_platform_data *pdata;
3131 int len = 0;
3132
3133 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
3134 if (!pdata) {
3135 pr_err("unable to allocate platform data\n");
3136 return NULL;
3137 }
3138 of_get_property(node, "qcom,hsusb-otg-phy-init-seq", &len);
3139 if (len) {
3140 pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
3141 if (!pdata->phy_init_seq)
3142 return NULL;
3143 of_property_read_u32_array(node, "qcom,hsusb-otg-phy-init-seq",
3144 pdata->phy_init_seq,
3145 len/sizeof(*pdata->phy_init_seq));
3146 }
3147 of_property_read_u32(node, "qcom,hsusb-otg-power-budget",
3148 &pdata->power_budget);
3149 of_property_read_u32(node, "qcom,hsusb-otg-mode",
3150 &pdata->mode);
3151 of_property_read_u32(node, "qcom,hsusb-otg-otg-control",
3152 &pdata->otg_control);
3153 of_property_read_u32(node, "qcom,hsusb-otg-default-mode",
3154 &pdata->default_mode);
3155 of_property_read_u32(node, "qcom,hsusb-otg-phy-type",
3156 &pdata->phy_type);
3157 of_property_read_u32(node, "qcom,hsusb-otg-pmic-id-irq",
3158 &pdata->pmic_id_irq);
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303159 return pdata;
3160}
3161
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303162static int __init msm_otg_probe(struct platform_device *pdev)
3163{
3164 int ret = 0;
3165 struct resource *res;
3166 struct msm_otg *motg;
3167 struct otg_transceiver *otg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303168 struct msm_otg_platform_data *pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303169
3170 dev_info(&pdev->dev, "msm_otg probe\n");
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303171
3172 if (pdev->dev.of_node) {
3173 dev_dbg(&pdev->dev, "device tree enabled\n");
3174 pdata = msm_otg_dt_to_pdata(pdev);
3175 if (!pdata)
3176 return -ENOMEM;
3177 ret = msm_otg_setup_devices(pdev, pdata->mode, true);
3178 if (ret) {
3179 dev_err(&pdev->dev, "devices setup failed\n");
3180 return ret;
3181 }
3182 } else if (!pdev->dev.platform_data) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303183 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
3184 return -ENODEV;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303185 } else {
3186 pdata = pdev->dev.platform_data;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303187 }
3188
3189 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
3190 if (!motg) {
3191 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
3192 return -ENOMEM;
3193 }
3194
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003195 the_msm_otg = motg;
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303196 motg->pdata = pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303197 otg = &motg->otg;
3198 otg->dev = &pdev->dev;
3199
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303200 /*
3201 * ACA ID_GND threshold range is overlapped with OTG ID_FLOAT. Hence
3202 * PHY treat ACA ID_GND as float and no interrupt is generated. But
3203 * PMIC can detect ACA ID_GND and generate an interrupt.
3204 */
3205 if (aca_enabled() && motg->pdata->otg_control != OTG_PMIC_CONTROL) {
3206 dev_err(&pdev->dev, "ACA can not be enabled without PMIC\n");
3207 ret = -EINVAL;
3208 goto free_motg;
3209 }
3210
Ofir Cohen4da266f2012-01-03 10:19:29 +02003211 /* initialize reset counter */
3212 motg->reset_counter = 0;
3213
Amit Blay02eff132011-09-21 16:46:24 +03003214 /* Some targets don't support PHY clock. */
Manu Gautam5143b252012-01-05 19:25:23 -08003215 motg->phy_reset_clk = clk_get(&pdev->dev, "phy_clk");
Amit Blay02eff132011-09-21 16:46:24 +03003216 if (IS_ERR(motg->phy_reset_clk))
Manu Gautam5143b252012-01-05 19:25:23 -08003217 dev_err(&pdev->dev, "failed to get phy_clk\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303218
Pavankumar Kondeti923262e2012-04-20 15:34:24 +05303219 /*
3220 * Targets on which link uses asynchronous reset methodology,
3221 * free running clock is not required during the reset.
3222 */
Manu Gautam5143b252012-01-05 19:25:23 -08003223 motg->clk = clk_get(&pdev->dev, "alt_core_clk");
Pavankumar Kondeti923262e2012-04-20 15:34:24 +05303224 if (IS_ERR(motg->clk))
3225 dev_dbg(&pdev->dev, "alt_core_clk is not present\n");
3226 else
3227 clk_set_rate(motg->clk, 60000000);
Anji jonnala0f73cac2011-05-04 10:19:46 +05303228
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05303229 /* pm qos request to prevent apps idle power collapse */
3230 if (motg->pdata->swfi_latency)
3231 pm_qos_add_request(&motg->pm_qos_req_dma,
3232 PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
Manu Gautam5143b252012-01-05 19:25:23 -08003233
Anji jonnala0f73cac2011-05-04 10:19:46 +05303234 /*
Manu Gautam5143b252012-01-05 19:25:23 -08003235 * USB Core is running its protocol engine based on CORE CLK,
Anji jonnala0f73cac2011-05-04 10:19:46 +05303236 * CORE CLK must be running at >55Mhz for correct HSUSB
3237 * operation and USB core cannot tolerate frequency changes on
3238 * CORE CLK. For such USB cores, vote for maximum clk frequency
3239 * on pclk source
3240 */
Manu Gautam5143b252012-01-05 19:25:23 -08003241 motg->core_clk = clk_get(&pdev->dev, "core_clk");
3242 if (IS_ERR(motg->core_clk)) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303243 motg->core_clk = NULL;
Manu Gautam5143b252012-01-05 19:25:23 -08003244 dev_err(&pdev->dev, "failed to get core_clk\n");
Pavankumar Kondetibc541332012-04-20 15:32:04 +05303245 ret = PTR_ERR(motg->core_clk);
Manu Gautam5143b252012-01-05 19:25:23 -08003246 goto put_clk;
3247 }
3248 clk_set_rate(motg->core_clk, INT_MAX);
3249
3250 motg->pclk = clk_get(&pdev->dev, "iface_clk");
3251 if (IS_ERR(motg->pclk)) {
3252 dev_err(&pdev->dev, "failed to get iface_clk\n");
3253 ret = PTR_ERR(motg->pclk);
3254 goto put_core_clk;
3255 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303256
3257 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3258 if (!res) {
3259 dev_err(&pdev->dev, "failed to get platform resource mem\n");
3260 ret = -ENODEV;
Manu Gautam5143b252012-01-05 19:25:23 -08003261 goto put_pclk;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303262 }
3263
3264 motg->regs = ioremap(res->start, resource_size(res));
3265 if (!motg->regs) {
3266 dev_err(&pdev->dev, "ioremap failed\n");
3267 ret = -ENOMEM;
Manu Gautam5143b252012-01-05 19:25:23 -08003268 goto put_pclk;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303269 }
3270 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
3271
3272 motg->irq = platform_get_irq(pdev, 0);
3273 if (!motg->irq) {
3274 dev_err(&pdev->dev, "platform_get_irq failed\n");
3275 ret = -ENODEV;
3276 goto free_regs;
3277 }
3278
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003279 motg->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, "usb");
Anji jonnala7da3f262011-12-02 17:22:14 -08003280 if (IS_ERR(motg->xo_handle)) {
3281 dev_err(&pdev->dev, "%s not able to get the handle "
3282 "to vote for TCXO D0 buffer\n", __func__);
3283 ret = PTR_ERR(motg->xo_handle);
3284 goto free_regs;
3285 }
3286
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003287 ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
Anji jonnala7da3f262011-12-02 17:22:14 -08003288 if (ret) {
3289 dev_err(&pdev->dev, "%s failed to vote for TCXO "
3290 "D0 buffer%d\n", __func__, ret);
3291 goto free_xo_handle;
3292 }
3293
Manu Gautam28b1bac2012-01-30 16:43:06 +05303294 clk_prepare_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05303295
Mayank Rana248698c2012-04-19 00:03:16 +05303296 motg->vdd_type = VDDCX_CORNER;
3297 hsusb_vddcx = devm_regulator_get(motg->otg.dev, "hsusb_vdd_dig");
3298 if (IS_ERR(hsusb_vddcx)) {
3299 hsusb_vddcx = devm_regulator_get(motg->otg.dev, "HSUSB_VDDCX");
3300 if (IS_ERR(hsusb_vddcx)) {
3301 dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
3302 goto devote_xo_handle;
3303 }
3304 motg->vdd_type = VDDCX;
Anji jonnala11aa5c42011-05-04 10:19:48 +05303305 }
3306
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003307 ret = msm_hsusb_config_vddcx(1);
3308 if (ret) {
3309 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
Mayank Rana248698c2012-04-19 00:03:16 +05303310 goto devote_xo_handle;
3311 }
3312
3313 ret = regulator_enable(hsusb_vddcx);
3314 if (ret) {
3315 dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
3316 goto free_config_vddcx;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003317 }
3318
Anji jonnala11aa5c42011-05-04 10:19:48 +05303319 ret = msm_hsusb_ldo_init(motg, 1);
3320 if (ret) {
3321 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Mayank Rana248698c2012-04-19 00:03:16 +05303322 goto free_hsusb_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05303323 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003324
Mayank Rana9e9a2ac2012-03-24 04:05:28 +05303325 if (pdata->mhl_enable) {
3326 mhl_analog_switch = devm_regulator_get(motg->otg.dev,
3327 "mhl_ext_3p3v");
3328 if (IS_ERR(mhl_analog_switch)) {
3329 dev_err(&pdev->dev, "Unable to get mhl_analog_switch\n");
3330 goto free_ldo_init;
3331 }
3332 }
3333
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003334 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05303335 if (ret) {
3336 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003337 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05303338 }
Manu Gautam28b1bac2012-01-30 16:43:06 +05303339 clk_prepare_enable(motg->core_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303340
3341 writel(0, USB_USBINTR);
3342 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003343 /* Ensure that above STOREs are completed before enabling interrupts */
3344 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303345
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003346 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05303347 msm_otg_init_timer(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303348 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303349 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303350 setup_timer(&motg->id_timer, msm_otg_id_timer_func,
3351 (unsigned long) motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303352 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
3353 "msm_otg", motg);
3354 if (ret) {
3355 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003356 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303357 }
3358
3359 otg->init = msm_otg_reset;
3360 otg->set_host = msm_otg_set_host;
3361 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303362 otg->set_power = msm_otg_set_power;
Vijayavardhan Vennapusaa3152032012-03-05 16:29:30 +05303363 otg->start_hnp = msm_otg_start_hnp;
3364 otg->start_srp = msm_otg_start_srp;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05303365 otg->set_suspend = msm_otg_set_suspend;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303366
3367 otg->io_ops = &msm_otg_io_ops;
3368
3369 ret = otg_set_transceiver(&motg->otg);
3370 if (ret) {
3371 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
3372 goto free_irq;
3373 }
3374
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05303375 if (motg->pdata->mode == USB_OTG &&
3376 motg->pdata->otg_control == OTG_PMIC_CONTROL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003377 if (motg->pdata->pmic_id_irq) {
3378 ret = request_irq(motg->pdata->pmic_id_irq,
3379 msm_pmic_id_irq,
3380 IRQF_TRIGGER_RISING |
3381 IRQF_TRIGGER_FALLING,
3382 "msm_otg", motg);
3383 if (ret) {
3384 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
3385 goto remove_otg;
3386 }
3387 } else {
3388 ret = -ENODEV;
3389 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
3390 goto remove_otg;
3391 }
3392 }
3393
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05303394 msm_hsusb_mhl_switch_enable(motg, 1);
3395
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303396 platform_set_drvdata(pdev, motg);
3397 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003398 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303399
Anji jonnalad270e2d2011-08-09 11:28:32 +05303400 ret = msm_otg_debugfs_init(motg);
3401 if (ret)
3402 dev_dbg(&pdev->dev, "mode debugfs file is"
3403 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303404
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003405 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
3406 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
3407
Amit Blay58b31472011-11-18 09:39:39 +02003408 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
3409 if (motg->pdata->otg_control == OTG_PMIC_CONTROL &&
Pavankumar Kondeti0d81f312012-01-13 11:34:10 +05303410 (!(motg->pdata->mode == USB_OTG) ||
3411 motg->pdata->pmic_id_irq))
Amit Blay58b31472011-11-18 09:39:39 +02003412 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003413 ALLOW_PHY_RETENTION |
3414 ALLOW_PHY_COMP_DISABLE;
3415
Amit Blay58b31472011-11-18 09:39:39 +02003416 if (motg->pdata->otg_control == OTG_PHY_CONTROL)
3417 motg->caps = ALLOW_PHY_RETENTION;
3418 }
3419
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003420 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303421 pm_runtime_set_active(&pdev->dev);
3422 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303423
Manu Gautamcd82e9d2011-12-20 14:17:28 +05303424 if (motg->pdata->bus_scale_table) {
3425 motg->bus_perf_client =
3426 msm_bus_scale_register_client(motg->pdata->bus_scale_table);
3427 if (!motg->bus_perf_client)
3428 dev_err(motg->otg.dev, "%s: Failed to register BUS "
3429 "scaling client!!\n", __func__);
Manu Gautam8bdcc592012-03-06 11:26:06 +05303430 else
3431 debug_bus_voting_enabled = true;
Manu Gautamcd82e9d2011-12-20 14:17:28 +05303432 }
3433
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303434 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003435
3436remove_otg:
3437 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303438free_irq:
3439 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003440destroy_wlock:
3441 wake_lock_destroy(&motg->wlock);
Manu Gautam28b1bac2012-01-30 16:43:06 +05303442 clk_disable_unprepare(motg->core_clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003443 msm_hsusb_ldo_enable(motg, 0);
3444free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05303445 msm_hsusb_ldo_init(motg, 0);
Mayank Rana248698c2012-04-19 00:03:16 +05303446free_hsusb_vddcx:
3447 regulator_disable(hsusb_vddcx);
3448free_config_vddcx:
3449 regulator_set_voltage(hsusb_vddcx,
3450 vdd_val[motg->vdd_type][VDD_NONE],
3451 vdd_val[motg->vdd_type][VDD_MAX]);
Anji jonnala7da3f262011-12-02 17:22:14 -08003452devote_xo_handle:
Manu Gautam28b1bac2012-01-30 16:43:06 +05303453 clk_disable_unprepare(motg->pclk);
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003454 msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
Anji jonnala7da3f262011-12-02 17:22:14 -08003455free_xo_handle:
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003456 msm_xo_put(motg->xo_handle);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303457free_regs:
3458 iounmap(motg->regs);
Manu Gautam5143b252012-01-05 19:25:23 -08003459put_pclk:
3460 clk_put(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303461put_core_clk:
Manu Gautam5143b252012-01-05 19:25:23 -08003462 clk_put(motg->core_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303463put_clk:
Pavankumar Kondeti923262e2012-04-20 15:34:24 +05303464 if (!IS_ERR(motg->clk))
3465 clk_put(motg->clk);
Amit Blay02eff132011-09-21 16:46:24 +03003466 if (!IS_ERR(motg->phy_reset_clk))
3467 clk_put(motg->phy_reset_clk);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05303468free_motg:
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05303469 if (motg->pdata->swfi_latency)
3470 pm_qos_remove_request(&motg->pm_qos_req_dma);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303471 kfree(motg);
3472 return ret;
3473}
3474
3475static int __devexit msm_otg_remove(struct platform_device *pdev)
3476{
3477 struct msm_otg *motg = platform_get_drvdata(pdev);
3478 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303479 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303480
3481 if (otg->host || otg->gadget)
3482 return -EBUSY;
3483
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303484 if (pdev->dev.of_node)
3485 msm_otg_setup_devices(pdev, motg->pdata->mode, false);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003486 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
3487 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303488 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05303489 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303490 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303491
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303492 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303493
3494 device_init_wakeup(&pdev->dev, 0);
3495 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003496 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303497
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05303498 msm_hsusb_mhl_switch_enable(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003499 if (motg->pdata->pmic_id_irq)
3500 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303501 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303502 free_irq(motg->irq, motg);
3503
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303504 /*
3505 * Put PHY in low power mode.
3506 */
3507 ulpi_read(otg, 0x14);
3508 ulpi_write(otg, 0x08, 0x09);
3509
3510 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
3511 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
3512 if (readl(USB_PORTSC) & PORTSC_PHCD)
3513 break;
3514 udelay(1);
3515 cnt++;
3516 }
3517 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
3518 dev_err(otg->dev, "Unable to suspend PHY\n");
3519
Manu Gautam28b1bac2012-01-30 16:43:06 +05303520 clk_disable_unprepare(motg->pclk);
3521 clk_disable_unprepare(motg->core_clk);
Stephen Boyd30ad10b2012-03-01 14:51:04 -08003522 msm_xo_put(motg->xo_handle);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003523 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05303524 msm_hsusb_ldo_init(motg, 0);
Mayank Rana248698c2012-04-19 00:03:16 +05303525 regulator_disable(hsusb_vddcx);
3526 regulator_set_voltage(hsusb_vddcx,
3527 vdd_val[motg->vdd_type][VDD_NONE],
3528 vdd_val[motg->vdd_type][VDD_MAX]);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303529
3530 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303531 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303532
Amit Blay02eff132011-09-21 16:46:24 +03003533 if (!IS_ERR(motg->phy_reset_clk))
3534 clk_put(motg->phy_reset_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303535 clk_put(motg->pclk);
Pavankumar Kondeti923262e2012-04-20 15:34:24 +05303536 if (!IS_ERR(motg->clk))
3537 clk_put(motg->clk);
Manu Gautam5143b252012-01-05 19:25:23 -08003538 clk_put(motg->core_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303539
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05303540 if (motg->pdata->swfi_latency)
3541 pm_qos_remove_request(&motg->pm_qos_req_dma);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303542
Manu Gautamcd82e9d2011-12-20 14:17:28 +05303543 if (motg->bus_perf_client)
3544 msm_bus_scale_unregister_client(motg->bus_perf_client);
3545
Anji jonnalaa7c1c5c2011-12-12 12:20:36 +05303546 kfree(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303547 return 0;
3548}
3549
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303550#ifdef CONFIG_PM_RUNTIME
3551static int msm_otg_runtime_idle(struct device *dev)
3552{
3553 struct msm_otg *motg = dev_get_drvdata(dev);
3554 struct otg_transceiver *otg = &motg->otg;
3555
3556 dev_dbg(dev, "OTG runtime idle\n");
3557
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05303558 if (otg->state == OTG_STATE_UNDEFINED)
3559 return -EAGAIN;
3560 else
3561 return 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303562}
3563
3564static int msm_otg_runtime_suspend(struct device *dev)
3565{
3566 struct msm_otg *motg = dev_get_drvdata(dev);
3567
3568 dev_dbg(dev, "OTG runtime suspend\n");
3569 return msm_otg_suspend(motg);
3570}
3571
3572static int msm_otg_runtime_resume(struct device *dev)
3573{
3574 struct msm_otg *motg = dev_get_drvdata(dev);
3575
3576 dev_dbg(dev, "OTG runtime resume\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05303577 pm_runtime_get_noresume(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303578 return msm_otg_resume(motg);
3579}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303580#endif
3581
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303582#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303583static int msm_otg_pm_suspend(struct device *dev)
3584{
Jack Phamd44455a2012-04-10 16:23:49 -07003585 struct msm_otg *motg = dev_get_drvdata(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303586
3587 dev_dbg(dev, "OTG PM suspend\n");
Jack Phamd44455a2012-04-10 16:23:49 -07003588 return msm_otg_suspend(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303589}
3590
3591static int msm_otg_pm_resume(struct device *dev)
3592{
3593 struct msm_otg *motg = dev_get_drvdata(dev);
Jack Phamd44455a2012-04-10 16:23:49 -07003594 int ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303595
3596 dev_dbg(dev, "OTG PM resume\n");
Jack Phamd44455a2012-04-10 16:23:49 -07003597 ret = msm_otg_resume(motg);
3598 if (ret)
3599 return ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303600
Jack Phamd44455a2012-04-10 16:23:49 -07003601 /* Update runtime PM status */
3602 pm_runtime_disable(dev);
3603 pm_runtime_set_active(dev);
3604 pm_runtime_enable(dev);
3605
Gregory Beanebd8ca22011-10-11 12:02:35 -07003606 return 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303607}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303608#endif
3609
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303610#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303611static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303612 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
3613 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
3614 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303615};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303616#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303617
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303618static struct of_device_id msm_otg_dt_match[] = {
3619 { .compatible = "qcom,hsusb-otg",
3620 },
3621 {}
3622};
3623
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303624static struct platform_driver msm_otg_driver = {
3625 .remove = __devexit_p(msm_otg_remove),
3626 .driver = {
3627 .name = DRIVER_NAME,
3628 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303629#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05303630 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05303631#endif
Pavankumar Kondetieaea7fe2011-10-27 14:46:45 +05303632 .of_match_table = msm_otg_dt_match,
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05303633 },
3634};
3635
3636static int __init msm_otg_init(void)
3637{
3638 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
3639}
3640
3641static void __exit msm_otg_exit(void)
3642{
3643 platform_driver_unregister(&msm_otg_driver);
3644}
3645
3646module_init(msm_otg_init);
3647module_exit(msm_otg_exit);
3648
3649MODULE_LICENSE("GPL v2");
3650MODULE_DESCRIPTION("MSM USB transceiver driver");