1d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
2e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti *
3e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * This program is free software; you can redistribute it and/or modify
4e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * it under the terms of the GNU General Public License version 2 and
5e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * only version 2 as published by the Free Software Foundation.
6e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti *
7e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * This program is distributed in the hope that it will be useful,
8e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * but WITHOUT ANY WARRANTY; without even the implied warranty of
9e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * GNU General Public License for more details.
11e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti *
12e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * You should have received a copy of the GNU General Public License
13e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * along with this program; if not, write to the Free Software
14e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * 02110-1301, USA.
16e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti *
17e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti */
18e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
19e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/module.h>
20e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/device.h>
21e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/platform_device.h>
22e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/clk.h>
23e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/slab.h>
24e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/interrupt.h>
25e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/err.h>
26e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/delay.h>
27e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/io.h>
28e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/ioport.h>
29e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/uaccess.h>
30e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/debugfs.h>
31e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/seq_file.h>
3287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti#include <linux/pm_runtime.h>
33e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
34e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/usb.h>
35e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/usb/otg.h>
36e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/usb/ulpi.h>
37e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/usb/gadget.h>
38e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/usb/hcd.h>
39e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/usb/msm_hsusb.h>
40e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <linux/usb/msm_hsusb_hw.h>
4111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#include <linux/regulator/consumer.h>
42e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
43e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#include <mach/clk.h>
44e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
45e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#define MSM_USB_BASE	(motg->regs)
46e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#define DRIVER_NAME	"msm_otg"
47e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
48e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
4911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
5011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_3P3_VOL_MIN	3050000 /* uV */
5111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_3P3_VOL_MAX	3300000 /* uV */
5211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_3P3_HPM_LOAD	50000	/* uA */
5311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_3P3_LPM_LOAD	4000	/* uA */
5411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
5511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_1P8_VOL_MIN	1800000 /* uV */
5611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_1P8_VOL_MAX	1800000 /* uV */
5711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_1P8_HPM_LOAD	50000	/* uA */
5811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_1P8_LPM_LOAD	4000	/* uA */
5911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
6011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_VDD_DIG_VOL_MIN	1000000 /* uV */
6111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala#define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */
6211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
6311aa5c478e743712228ff2da881b85100800c1eeAnji jonnalastatic struct regulator *hsusb_3p3;
6411aa5c478e743712228ff2da881b85100800c1eeAnji jonnalastatic struct regulator *hsusb_1p8;
6511aa5c478e743712228ff2da881b85100800c1eeAnji jonnalastatic struct regulator *hsusb_vddcx;
6611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
6711aa5c478e743712228ff2da881b85100800c1eeAnji jonnalastatic int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
6811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala{
6911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	int ret = 0;
7011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
7111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	if (init) {
721d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		hsusb_vddcx = regulator_get(motg->phy.dev, "HSUSB_VDDCX");
7311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (IS_ERR(hsusb_vddcx)) {
741d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to get hsusb vddcx\n");
7511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			return PTR_ERR(hsusb_vddcx);
7611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
7711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
7811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		ret = regulator_set_voltage(hsusb_vddcx,
7911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				USB_PHY_VDD_DIG_VOL_MIN,
8011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				USB_PHY_VDD_DIG_VOL_MAX);
8111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (ret) {
821d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to set the voltage "
8311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala					"for hsusb vddcx\n");
8411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			regulator_put(hsusb_vddcx);
8511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			return ret;
8611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
8711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
8811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		ret = regulator_enable(hsusb_vddcx);
8911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (ret) {
901d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to enable hsusb vddcx\n");
9111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			regulator_put(hsusb_vddcx);
9211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
9311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	} else {
9411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		ret = regulator_set_voltage(hsusb_vddcx, 0,
957b521fcb6bf63a49bb7712d922dd1dd0a90a93cfMark Brown			USB_PHY_VDD_DIG_VOL_MAX);
96e99c4309fb064604a957d9c1a8d2d4a9ff19cf5eMark Brown		if (ret)
971d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to set the voltage "
9811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala					"for hsusb vddcx\n");
9911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		ret = regulator_disable(hsusb_vddcx);
10011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (ret)
1011d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to disable hsusb vddcx\n");
10211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
10311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		regulator_put(hsusb_vddcx);
10411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	}
10511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
10611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	return ret;
10711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala}
10811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
10911aa5c478e743712228ff2da881b85100800c1eeAnji jonnalastatic int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
11011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala{
11111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	int rc = 0;
11211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
11311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	if (init) {
1141d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		hsusb_3p3 = regulator_get(motg->phy.dev, "HSUSB_3p3");
11511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (IS_ERR(hsusb_3p3)) {
1161d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to get hsusb 3p3\n");
11711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			return PTR_ERR(hsusb_3p3);
11811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
11911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
12011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
12111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				USB_PHY_3P3_VOL_MAX);
12211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (rc) {
1231d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to set voltage level "
12411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala					"for hsusb 3p3\n");
12511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			goto put_3p3;
12611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
12711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		rc = regulator_enable(hsusb_3p3);
12811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (rc) {
1291d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to enable the hsusb 3p3\n");
13011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			goto put_3p3;
13111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
1321d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		hsusb_1p8 = regulator_get(motg->phy.dev, "HSUSB_1p8");
13311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (IS_ERR(hsusb_1p8)) {
1341d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to get hsusb 1p8\n");
13511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			rc = PTR_ERR(hsusb_1p8);
13611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			goto disable_3p3;
13711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
13811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
13911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				USB_PHY_1P8_VOL_MAX);
14011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (rc) {
1411d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to set voltage level "
14211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala					"for hsusb 1p8\n");
14311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			goto put_1p8;
14411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
14511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		rc = regulator_enable(hsusb_1p8);
14611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (rc) {
1471d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "unable to enable the hsusb 1p8\n");
14811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			goto put_1p8;
14911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
15011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
15111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		return 0;
15211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	}
15311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
15411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	regulator_disable(hsusb_1p8);
15511aa5c478e743712228ff2da881b85100800c1eeAnji jonnalaput_1p8:
15611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	regulator_put(hsusb_1p8);
15711aa5c478e743712228ff2da881b85100800c1eeAnji jonnaladisable_3p3:
15811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	regulator_disable(hsusb_3p3);
15911aa5c478e743712228ff2da881b85100800c1eeAnji jonnalaput_3p3:
16011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	regulator_put(hsusb_3p3);
16111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	return rc;
16211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala}
16311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
16404aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti#ifdef CONFIG_PM_SLEEP
16504aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti#define USB_PHY_SUSP_DIG_VOL  500000
16604aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondetistatic int msm_hsusb_config_vddcx(int high)
16704aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti{
16804aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
16904aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	int min_vol;
17004aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	int ret;
17104aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti
17204aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	if (high)
17304aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		min_vol = USB_PHY_VDD_DIG_VOL_MIN;
17404aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	else
17504aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		min_vol = USB_PHY_SUSP_DIG_VOL;
17604aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti
17704aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
17804aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	if (ret) {
17904aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		pr_err("%s: unable to set the voltage for regulator "
18004aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti			"HSUSB_VDDCX\n", __func__);
18104aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		return ret;
18204aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	}
18304aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti
18404aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
18504aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti
18604aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	return ret;
18704aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti}
18804aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti#endif
18904aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti
19011aa5c478e743712228ff2da881b85100800c1eeAnji jonnalastatic int msm_hsusb_ldo_set_mode(int on)
19111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala{
19211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	int ret = 0;
19311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
19411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
19511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
19611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		return -ENODEV;
19711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	}
19811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
19911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
20011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
20111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		return -ENODEV;
20211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	}
20311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
20411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	if (on) {
20511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		ret = regulator_set_optimum_mode(hsusb_1p8,
20611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				USB_PHY_1P8_HPM_LOAD);
20711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (ret < 0) {
20811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			pr_err("%s: Unable to set HPM of the regulator "
20911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				"HSUSB_1p8\n", __func__);
21011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			return ret;
21111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
21211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		ret = regulator_set_optimum_mode(hsusb_3p3,
21311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				USB_PHY_3P3_HPM_LOAD);
21411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (ret < 0) {
21511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			pr_err("%s: Unable to set HPM of the regulator "
21611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				"HSUSB_3p3\n", __func__);
21711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			regulator_set_optimum_mode(hsusb_1p8,
21811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				USB_PHY_1P8_LPM_LOAD);
21911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			return ret;
22011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		}
22111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	} else {
22211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		ret = regulator_set_optimum_mode(hsusb_1p8,
22311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				USB_PHY_1P8_LPM_LOAD);
22411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (ret < 0)
22511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			pr_err("%s: Unable to set LPM of the regulator "
22611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				"HSUSB_1p8\n", __func__);
22711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		ret = regulator_set_optimum_mode(hsusb_3p3,
22811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				USB_PHY_3P3_LPM_LOAD);
22911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		if (ret < 0)
23011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala			pr_err("%s: Unable to set LPM of the regulator "
23111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala				"HSUSB_3p3\n", __func__);
23211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	}
23311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
23411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
23511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	return ret < 0 ? ret : 0;
23611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala}
23711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
2381d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerusstatic int ulpi_read(struct usb_phy *phy, u32 reg)
239e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
2401d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
241e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int cnt = 0;
242e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
243e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/* initiate read operation */
244e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
245e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	       USB_ULPI_VIEWPORT);
246e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
247e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/* wait for completion */
248e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	while (cnt < ULPI_IO_TIMEOUT_USEC) {
249e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
250e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			break;
251e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		udelay(1);
252e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		cnt++;
253e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
254e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
255e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
2561d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(phy->dev, "ulpi_read: timeout %08x\n",
257e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			readl(USB_ULPI_VIEWPORT));
258e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ETIMEDOUT;
259e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
260e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
261e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
262e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
2631d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerusstatic int ulpi_write(struct usb_phy *phy, u32 val, u32 reg)
264e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
2651d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
266e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int cnt = 0;
267e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
268e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/* initiate write operation */
269e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(ULPI_RUN | ULPI_WRITE |
270e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	       ULPI_ADDR(reg) | ULPI_DATA(val),
271e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	       USB_ULPI_VIEWPORT);
272e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
273e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/* wait for completion */
274e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	while (cnt < ULPI_IO_TIMEOUT_USEC) {
275e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
276e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			break;
277e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		udelay(1);
278e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		cnt++;
279e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
280e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
281e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
2821d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(phy->dev, "ulpi_write: timeout\n");
283e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ETIMEDOUT;
284e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
285e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return 0;
286e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
287e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
2881d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerusstatic struct usb_phy_io_ops msm_otg_io_ops = {
289e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	.read = ulpi_read,
290e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	.write = ulpi_write,
291e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti};
292e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
293e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic void ulpi_init(struct msm_otg *motg)
294e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
295e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg_platform_data *pdata = motg->pdata;
296e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int *seq = pdata->phy_init_seq;
297e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
298e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!seq)
299e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return;
300e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
301e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	while (seq[0] >= 0) {
3021d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n",
303e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				seq[0], seq[1]);
3041d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(&motg->phy, seq[0], seq[1]);
305e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		seq += 2;
306e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
307e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
308e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
309e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
310e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
311e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int ret;
312e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
313e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (assert) {
314e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
315e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (ret)
3161d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "usb hs_clk assert failed\n");
317e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	} else {
318e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
319e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (ret)
3201d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			dev_err(motg->phy.dev, "usb hs_clk deassert failed\n");
321e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
322e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return ret;
323e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
324e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
325e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic int msm_otg_phy_clk_reset(struct msm_otg *motg)
326e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
327e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int ret;
328e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
329e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
330e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (ret) {
3311d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(motg->phy.dev, "usb phy clk assert failed\n");
332e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return ret;
333e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
334e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	usleep_range(10000, 12000);
335e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
336e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (ret)
3371d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(motg->phy.dev, "usb phy clk deassert failed\n");
338e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return ret;
339e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
340e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
341e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic int msm_otg_phy_reset(struct msm_otg *motg)
342e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
343e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	u32 val;
344e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int ret;
345e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int retries;
346e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
347e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	ret = msm_otg_link_clk_reset(motg, 1);
348e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (ret)
349e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return ret;
350e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	ret = msm_otg_phy_clk_reset(motg);
351e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (ret)
352e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return ret;
353e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	ret = msm_otg_link_clk_reset(motg, 0);
354e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (ret)
355e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return ret;
356e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
357e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
358e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
359e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
360e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	for (retries = 3; retries > 0; retries--) {
3611d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ret = ulpi_write(&motg->phy, ULPI_FUNC_CTRL_SUSPENDM,
362e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				ULPI_CLR(ULPI_FUNC_CTRL));
363e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (!ret)
364e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			break;
365e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = msm_otg_phy_clk_reset(motg);
366e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (ret)
367e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			return ret;
368e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
369e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!retries)
370e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ETIMEDOUT;
371e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
372e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/* This reset calibrates the phy, if the above write succeeded */
373e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	ret = msm_otg_phy_clk_reset(motg);
374e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (ret)
375e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return ret;
376e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
377e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	for (retries = 3; retries > 0; retries--) {
3781d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ret = ulpi_read(&motg->phy, ULPI_DEBUG);
379e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (ret != -ETIMEDOUT)
380e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			break;
381e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = msm_otg_phy_clk_reset(motg);
382e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (ret)
383e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			return ret;
384e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
385e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!retries)
386e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ETIMEDOUT;
387e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
3881d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	dev_info(motg->phy.dev, "phy_reset: success\n");
389e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return 0;
390e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
391e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
392e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
3931d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerusstatic int msm_otg_reset(struct usb_phy *phy)
394e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
3951d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
396e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg_platform_data *pdata = motg->pdata;
397e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int cnt = 0;
398e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int ret;
399e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	u32 val = 0;
400e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	u32 ulpi_val = 0;
401e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
402e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	ret = msm_otg_phy_reset(motg);
403e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (ret) {
4041d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(phy->dev, "phy_reset failed\n");
405e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return ret;
406e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
407e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
408e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	ulpi_init(motg);
409e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
410e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(USBCMD_RESET, USB_USBCMD);
411e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	while (cnt < LINK_RESET_TIMEOUT_USEC) {
412e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (!(readl(USB_USBCMD) & USBCMD_RESET))
413e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			break;
414e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		udelay(1);
415e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		cnt++;
416e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
417e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (cnt >= LINK_RESET_TIMEOUT_USEC)
418e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ETIMEDOUT;
419e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
420e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/* select ULPI phy */
421e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(0x80000000, USB_PORTSC);
422e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
423e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	msleep(100);
424e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
425e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(0x0, USB_AHBBURST);
426e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(0x00, USB_AHBMODE);
427e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
428e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (pdata->otg_control == OTG_PHY_CONTROL) {
429e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		val = readl(USB_OTGSC);
430e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (pdata->mode == USB_OTG) {
431e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
432e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			val |= OTGSC_IDIE | OTGSC_BSVIE;
433e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		} else if (pdata->mode == USB_PERIPHERAL) {
434e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			ulpi_val = ULPI_INT_SESS_VALID;
435e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			val |= OTGSC_BSVIE;
436e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
437e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		writel(val, USB_OTGSC);
4381d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE);
4391d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL);
440e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
441e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
442e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return 0;
443e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
444e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
44587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti#define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
4467018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti#define PHY_RESUME_TIMEOUT_USEC	(100 * 1000)
4477018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti
4487018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti#ifdef CONFIG_PM_SLEEP
44987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondetistatic int msm_otg_suspend(struct msm_otg *motg)
45087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti{
4511d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
4521d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_bus *bus = phy->otg->host;
45387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	struct msm_otg_platform_data *pdata = motg->pdata;
45487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	int cnt = 0;
45587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
45687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (atomic_read(&motg->in_lpm))
45787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		return 0;
45887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
45987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	disable_irq(motg->irq);
46087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	/*
46104aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	 * Chipidea 45-nm PHY suspend sequence:
46204aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	 *
46387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * Interrupt Latch Register auto-clear feature is not present
46487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * in all PHY versions. Latch register is clear on read type.
46587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * Clear latch register to avoid spurious wakeup from
46687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * low power mode (LPM).
46704aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	 *
46887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * PHY comparators are disabled when PHY enters into low power
46987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
47087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
47187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * PHY comparators. This save significant amount of power.
47204aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	 *
47387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * PLL is not turned off when PHY enters into low power mode (LPM).
47487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * Disable PLL for maximum power savings.
47587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 */
47604aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti
47704aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
4781d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_read(phy, 0x14);
47904aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		if (pdata->otg_control == OTG_PHY_CONTROL)
4801d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			ulpi_write(phy, 0x01, 0x30);
4811d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x08, 0x09);
48204aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	}
48387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
48487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	/*
48587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * PHY may take some time or even fail to enter into low power
48687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
48787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * in failure case.
48887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 */
48987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
49087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
49187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		if (readl(USB_PORTSC) & PORTSC_PHCD)
49287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti			break;
49387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		udelay(1);
49487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		cnt++;
49587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	}
49687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
49787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
4981d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(phy->dev, "Unable to suspend PHY\n");
4991d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		msm_otg_reset(phy);
50087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		enable_irq(motg->irq);
50187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		return -ETIMEDOUT;
50287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	}
50387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
50487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	/*
50587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * PHY has capability to generate interrupt asynchronously in low
50687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * power mode (LPM). This interrupt is level triggered. So USB IRQ
50787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * line must be disabled till async interrupt enable bit is cleared
50887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
50987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * block data communication from PHY.
51087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 */
51187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
51287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
51304aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
51404aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti			motg->pdata->otg_control == OTG_PMIC_CONTROL)
51504aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
51604aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti
51787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	clk_disable(motg->pclk);
51887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	clk_disable(motg->clk);
51987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (motg->core_clk)
52087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		clk_disable(motg->core_clk);
52187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
5220f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	if (!IS_ERR(motg->pclk_src))
5230f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		clk_disable(motg->pclk_src);
5240f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala
52504aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
52604aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti			motg->pdata->otg_control == OTG_PMIC_CONTROL) {
52704aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		msm_hsusb_ldo_set_mode(0);
52804aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		msm_hsusb_config_vddcx(0);
52904aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	}
53004aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti
5311d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	if (device_may_wakeup(phy->dev))
53287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		enable_irq_wake(motg->irq);
53387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (bus)
53487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
53587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
53687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	atomic_set(&motg->in_lpm, 1);
53787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	enable_irq(motg->irq);
53887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
5391d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	dev_info(phy->dev, "USB in low power mode\n");
54087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
54187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	return 0;
54287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti}
54387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
54487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondetistatic int msm_otg_resume(struct msm_otg *motg)
54587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti{
5461d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
5471d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_bus *bus = phy->otg->host;
54887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	int cnt = 0;
54987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	unsigned temp;
55087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
55187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (!atomic_read(&motg->in_lpm))
55287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		return 0;
55387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
5540f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	if (!IS_ERR(motg->pclk_src))
5550f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		clk_enable(motg->pclk_src);
5560f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala
55787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	clk_enable(motg->pclk);
55887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	clk_enable(motg->clk);
55987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (motg->core_clk)
56087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		clk_enable(motg->core_clk);
56187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
56204aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
56304aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti			motg->pdata->otg_control == OTG_PMIC_CONTROL) {
56404aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		msm_hsusb_ldo_set_mode(1);
56504aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		msm_hsusb_config_vddcx(1);
56604aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti		writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
56704aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti	}
56804aebcbb1b6dccadc8862b2765265f65a946db57Pavankumar Kondeti
56987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	temp = readl(USB_USBCMD);
57087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	temp &= ~ASYNC_INTR_CTRL;
57187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	temp &= ~ULPI_STP_CTRL;
57287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	writel(temp, USB_USBCMD);
57387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
57487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	/*
57587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * PHY comes out of low power mode (LPM) in case of wakeup
57687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * from asynchronous interrupt.
57787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 */
57887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (!(readl(USB_PORTSC) & PORTSC_PHCD))
57987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		goto skip_phy_resume;
58087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
58187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
58287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	while (cnt < PHY_RESUME_TIMEOUT_USEC) {
58387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		if (!(readl(USB_PORTSC) & PORTSC_PHCD))
58487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti			break;
58587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		udelay(1);
58687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		cnt++;
58787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	}
58887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
58987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
59087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		/*
59187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		 * This is a fatal error. Reset the link and
59287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		 * PHY. USB state can not be restored. Re-insertion
59387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		 * of USB cable is the only way to get USB working.
59487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		 */
5951d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(phy->dev, "Unable to resume USB."
59687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti				"Re-plugin the cable\n");
5971d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		msm_otg_reset(phy);
59887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	}
59987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
60087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondetiskip_phy_resume:
6011d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	if (device_may_wakeup(phy->dev))
60287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		disable_irq_wake(motg->irq);
60387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (bus)
60487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
60587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
6062ce2c3ac8852cfc8f74f4b7b9a2c4cdff007f96aPavankumar Kondeti	atomic_set(&motg->in_lpm, 0);
6072ce2c3ac8852cfc8f74f4b7b9a2c4cdff007f96aPavankumar Kondeti
60887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (motg->async_int) {
60987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		motg->async_int = 0;
6101d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		pm_runtime_put(phy->dev);
61187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		enable_irq(motg->irq);
61287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	}
61387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
6141d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	dev_info(phy->dev, "USB exited from low power mode\n");
61587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
61687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	return 0;
61787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti}
6187018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti#endif
61987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
620d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
621d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
622d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	if (motg->cur_power == mA)
623d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		return;
624d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
625d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	/* TODO: Notify PMIC about available current */
6261d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA);
627d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	motg->cur_power = mA;
628d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
629d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
6301d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerusstatic int msm_otg_set_power(struct usb_phy *phy, unsigned mA)
631d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
6321d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
633d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
634d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	/*
635d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	 * Gadget driver uses set_power method to notify about the
636d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	 * available current based on suspend/configured states.
637d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	 *
638d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	 * IDEV_CHG can be drawn irrespective of suspend/un-configured
639d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	 * states when CDP/ACA is connected.
640d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	 */
641d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	if (motg->chg_type == USB_SDP_CHARGER)
642d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		msm_otg_notify_charger(motg, mA);
643d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
644d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	return 0;
645d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
646d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
6471d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerusstatic void msm_otg_start_host(struct usb_phy *phy, int on)
648e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
6491d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
650e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg_platform_data *pdata = motg->pdata;
651e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct usb_hcd *hcd;
652e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
6531d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	if (!phy->otg->host)
654e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return;
655e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
6561d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	hcd = bus_to_hcd(phy->otg->host);
657e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
658e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (on) {
6591d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(phy->dev, "host on\n");
660e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
661e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (pdata->vbus_power)
662e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			pdata->vbus_power(1);
663e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		/*
664e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		 * Some boards have a switch cotrolled by gpio
665e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		 * to enable/disable internal HUB. Enable internal
666e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		 * HUB before kicking the host.
667e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		 */
668e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (pdata->setup_gpio)
669e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			pdata->setup_gpio(OTG_STATE_A_HOST);
670e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#ifdef CONFIG_USB
671e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
672e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#endif
673e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	} else {
6741d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(phy->dev, "host off\n");
675e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
676e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#ifdef CONFIG_USB
677e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		usb_remove_hcd(hcd);
678e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti#endif
679e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (pdata->setup_gpio)
680e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			pdata->setup_gpio(OTG_STATE_UNDEFINED);
681e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (pdata->vbus_power)
682e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			pdata->vbus_power(0);
683e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
684e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
685e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
6861d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerusstatic int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
687e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
6881d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
689e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct usb_hcd *hcd;
690e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
691e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/*
692e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * Fail host registration if this board can support
693e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * only peripheral configuration.
694e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 */
695e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (motg->pdata->mode == USB_PERIPHERAL) {
6961d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_info(otg->phy->dev, "Host mode is not supported\n");
697e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ENODEV;
698e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
699e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
700e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!host) {
7011d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		if (otg->phy->state == OTG_STATE_A_HOST) {
7021d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			pm_runtime_get_sync(otg->phy->dev);
7031d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			msm_otg_start_host(otg->phy, 0);
704e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			otg->host = NULL;
7051d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			otg->phy->state = OTG_STATE_UNDEFINED;
706e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			schedule_work(&motg->sm_work);
707e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		} else {
708e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			otg->host = NULL;
709e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
710e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
711e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return 0;
712e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
713e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
714e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	hcd = bus_to_hcd(host);
715e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	hcd->power_budget = motg->pdata->power_budget;
716e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
717e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	otg->host = host;
7181d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	dev_dbg(otg->phy->dev, "host driver registered w/ tranceiver\n");
719e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
720e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/*
721e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * Kick the state machine work, if peripheral is not supported
722e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * or peripheral is already registered with us.
723e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 */
72487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (motg->pdata->mode == USB_HOST || otg->gadget) {
7251d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		pm_runtime_get_sync(otg->phy->dev);
726e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		schedule_work(&motg->sm_work);
72787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	}
728e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
729e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return 0;
730e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
731e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
7321d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerusstatic void msm_otg_start_peripheral(struct usb_phy *phy, int on)
733e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
7341d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
735e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg_platform_data *pdata = motg->pdata;
736e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
7371d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	if (!phy->otg->gadget)
738e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return;
739e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
740e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (on) {
7411d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(phy->dev, "gadget on\n");
742e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		/*
743e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		 * Some boards have a switch cotrolled by gpio
744e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		 * to enable/disable internal HUB. Disable internal
745e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		 * HUB before kicking the gadget.
746e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		 */
747e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (pdata->setup_gpio)
748e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
7491d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		usb_gadget_vbus_connect(phy->otg->gadget);
750e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	} else {
7511d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(phy->dev, "gadget off\n");
7521d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		usb_gadget_vbus_disconnect(phy->otg->gadget);
753e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (pdata->setup_gpio)
754e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			pdata->setup_gpio(OTG_STATE_UNDEFINED);
755e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
756e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
757e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
758e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
7591d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerusstatic int msm_otg_set_peripheral(struct usb_otg *otg,
7601d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus					struct usb_gadget *gadget)
761e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
7621d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
763e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
764e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/*
765e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * Fail peripheral registration if this board can support
766e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * only host configuration.
767e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 */
768e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (motg->pdata->mode == USB_HOST) {
7691d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_info(otg->phy->dev, "Peripheral mode is not supported\n");
770e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ENODEV;
771e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
772e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
773e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!gadget) {
7741d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		if (otg->phy->state == OTG_STATE_B_PERIPHERAL) {
7751d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			pm_runtime_get_sync(otg->phy->dev);
7761d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			msm_otg_start_peripheral(otg->phy, 0);
777e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			otg->gadget = NULL;
7781d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			otg->phy->state = OTG_STATE_UNDEFINED;
779e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			schedule_work(&motg->sm_work);
780e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		} else {
781e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			otg->gadget = NULL;
782e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
783e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
784e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return 0;
785e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
786e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	otg->gadget = gadget;
7871d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	dev_dbg(otg->phy->dev, "peripheral driver registered w/ tranceiver\n");
788e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
789e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/*
790e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * Kick the state machine work, if host is not supported
791e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * or host is already registered with us.
792e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 */
79387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
7941d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		pm_runtime_get_sync(otg->phy->dev);
795e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		schedule_work(&motg->sm_work);
79687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	}
797e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
798e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return 0;
799e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
800e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
801d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic bool msm_chg_check_secondary_det(struct msm_otg *motg)
802d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
8031d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
804d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	u32 chg_det;
805d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	bool ret = false;
806d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
807d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->pdata->phy_type) {
808d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case CI_45NM_INTEGRATED_PHY:
8091d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x34);
810d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		ret = chg_det & (1 << 4);
811d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
812d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case SNPS_28NM_INTEGRATED_PHY:
8131d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x87);
814d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		ret = chg_det & 1;
815d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
816d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
817d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
818d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
819d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	return ret;
820d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
821d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
822d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic void msm_chg_enable_secondary_det(struct msm_otg *motg)
823d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
8241d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
825d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	u32 chg_det;
826d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
827d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->pdata->phy_type) {
828d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case CI_45NM_INTEGRATED_PHY:
8291d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x34);
830d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Turn off charger block */
831d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det |= ~(1 << 1);
8321d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
833d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		udelay(20);
834d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* control chg block via ULPI */
835d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det &= ~(1 << 3);
8361d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
837d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* put it in host mode for enabling D- source */
838d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det &= ~(1 << 2);
8391d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
840d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Turn on chg detect block */
841d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det &= ~(1 << 1);
8421d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
843d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		udelay(20);
844d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* enable chg detection */
845d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det &= ~(1 << 0);
8461d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
847d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
848d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case SNPS_28NM_INTEGRATED_PHY:
849d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/*
850d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		 * Configure DM as current source, DP as current sink
851d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		 * and enable battery charging comparators.
852d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		 */
8531d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x8, 0x85);
8541d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x2, 0x85);
8551d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x1, 0x85);
856d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
857d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
858d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
859d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
860d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
861d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
862d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic bool msm_chg_check_primary_det(struct msm_otg *motg)
863d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
8641d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
865d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	u32 chg_det;
866d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	bool ret = false;
867d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
868d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->pdata->phy_type) {
869d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case CI_45NM_INTEGRATED_PHY:
8701d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x34);
871d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		ret = chg_det & (1 << 4);
872d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
873d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case SNPS_28NM_INTEGRATED_PHY:
8741d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x87);
875d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		ret = chg_det & 1;
876d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
877d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
878d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
879d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
880d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	return ret;
881d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
882d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
883d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic void msm_chg_enable_primary_det(struct msm_otg *motg)
884d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
8851d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
886d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	u32 chg_det;
887d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
888d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->pdata->phy_type) {
889d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case CI_45NM_INTEGRATED_PHY:
8901d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x34);
891d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* enable chg detection */
892d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det &= ~(1 << 0);
8931d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
894d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
895d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case SNPS_28NM_INTEGRATED_PHY:
896d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/*
897d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		 * Configure DP as current source, DM as current sink
898d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		 * and enable battery charging comparators.
899d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		 */
9001d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x2, 0x85);
9011d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x1, 0x85);
902d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
903d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
904d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
905d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
906d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
907d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
908d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic bool msm_chg_check_dcd(struct msm_otg *motg)
909d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
9101d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
911d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	u32 line_state;
912d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	bool ret = false;
913d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
914d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->pdata->phy_type) {
915d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case CI_45NM_INTEGRATED_PHY:
9161d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		line_state = ulpi_read(phy, 0x15);
917d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		ret = !(line_state & 1);
918d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
919d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case SNPS_28NM_INTEGRATED_PHY:
9201d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		line_state = ulpi_read(phy, 0x87);
921d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		ret = line_state & 2;
922d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
923d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
924d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
925d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
926d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	return ret;
927d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
928d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
929d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic void msm_chg_disable_dcd(struct msm_otg *motg)
930d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
9311d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
932d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	u32 chg_det;
933d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
934d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->pdata->phy_type) {
935d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case CI_45NM_INTEGRATED_PHY:
9361d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x34);
937d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det &= ~(1 << 5);
9381d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
939d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
940d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case SNPS_28NM_INTEGRATED_PHY:
9411d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x10, 0x86);
942d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
943d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
944d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
945d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
946d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
947d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
948d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic void msm_chg_enable_dcd(struct msm_otg *motg)
949d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
9501d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
951d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	u32 chg_det;
952d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
953d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->pdata->phy_type) {
954d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case CI_45NM_INTEGRATED_PHY:
9551d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x34);
956d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Turn on D+ current source */
957d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det |= (1 << 5);
9581d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
959d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
960d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case SNPS_28NM_INTEGRATED_PHY:
961d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Data contact detection enable */
9621d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x10, 0x85);
963d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
964d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
965d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
966d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
967d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
968d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
969d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic void msm_chg_block_on(struct msm_otg *motg)
970d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
9711d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
972d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	u32 func_ctrl, chg_det;
973d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
974d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	/* put the controller in non-driving mode */
9751d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
976d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
977d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
9781d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
979d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
980d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->pdata->phy_type) {
981d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case CI_45NM_INTEGRATED_PHY:
9821d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x34);
983d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* control chg block via ULPI */
984d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det &= ~(1 << 3);
9851d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
986d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Turn on chg detect block */
987d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det &= ~(1 << 1);
9881d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
989d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		udelay(20);
990d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
991d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case SNPS_28NM_INTEGRATED_PHY:
992d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Clear charger detecting control bits */
9931d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x3F, 0x86);
994d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Clear alt interrupt latch and enable bits */
9951d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x1F, 0x92);
9961d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x1F, 0x95);
997d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		udelay(100);
998d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
999d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
1000d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
1001d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
1002d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
1003d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
1004d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic void msm_chg_block_off(struct msm_otg *motg)
1005d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
10061d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
1007d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	u32 func_ctrl, chg_det;
1008d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
1009d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->pdata->phy_type) {
1010d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case CI_45NM_INTEGRATED_PHY:
10111d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		chg_det = ulpi_read(phy, 0x34);
1012d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Turn off charger block */
1013d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		chg_det |= ~(1 << 1);
10141d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, chg_det, 0x34);
1015d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
1016d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case SNPS_28NM_INTEGRATED_PHY:
1017d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Clear charger detecting control bits */
10181d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x3F, 0x86);
1019d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* Clear alt interrupt latch and enable bits */
10201d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x1F, 0x92);
10211d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		ulpi_write(phy, 0x1F, 0x95);
1022d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
1023d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
1024d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
1025d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
1026d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
1027d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	/* put the controller in normal mode */
10281d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
1029d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1030d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
10311d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
1032d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
1033d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
1034d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti#define MSM_CHG_DCD_POLL_TIME		(100 * HZ/1000) /* 100 msec */
1035d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti#define MSM_CHG_DCD_MAX_RETRIES		6 /* Tdcd_tmout = 6 * 100 msec */
1036d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti#define MSM_CHG_PRIMARY_DET_TIME	(40 * HZ/1000) /* TVDPSRC_ON */
1037d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti#define MSM_CHG_SECONDARY_DET_TIME	(40 * HZ/1000) /* TVDMSRC_ON */
1038d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondetistatic void msm_chg_detect_work(struct work_struct *w)
1039d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti{
1040d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
10411d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
1042d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	bool is_dcd, tmout, vout;
1043d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	unsigned long delay;
1044d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
10451d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	dev_dbg(phy->dev, "chg detection work\n");
1046d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	switch (motg->chg_state) {
1047d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case USB_CHG_STATE_UNDEFINED:
10481d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		pm_runtime_get_sync(phy->dev);
1049d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		msm_chg_block_on(motg);
1050d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		msm_chg_enable_dcd(motg);
1051d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1052d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		motg->dcd_retries = 0;
1053d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		delay = MSM_CHG_DCD_POLL_TIME;
1054d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
1055d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case USB_CHG_STATE_WAIT_FOR_DCD:
1056d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		is_dcd = msm_chg_check_dcd(motg);
1057d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1058d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		if (is_dcd || tmout) {
1059d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			msm_chg_disable_dcd(motg);
1060d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			msm_chg_enable_primary_det(motg);
1061d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			delay = MSM_CHG_PRIMARY_DET_TIME;
1062d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_state = USB_CHG_STATE_DCD_DONE;
1063d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		} else {
1064d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			delay = MSM_CHG_DCD_POLL_TIME;
1065d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		}
1066d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
1067d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case USB_CHG_STATE_DCD_DONE:
1068d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		vout = msm_chg_check_primary_det(motg);
1069d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		if (vout) {
1070d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			msm_chg_enable_secondary_det(motg);
1071d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			delay = MSM_CHG_SECONDARY_DET_TIME;
1072d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1073d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		} else {
1074d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_type = USB_SDP_CHARGER;
1075d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_state = USB_CHG_STATE_DETECTED;
1076d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			delay = 0;
1077d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		}
1078d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		break;
1079d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case USB_CHG_STATE_PRIMARY_DONE:
1080d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		vout = msm_chg_check_secondary_det(motg);
1081d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		if (vout)
1082d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_type = USB_DCP_CHARGER;
1083d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		else
1084d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_type = USB_CDP_CHARGER;
1085d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1086d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		/* fall through */
1087d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case USB_CHG_STATE_SECONDARY_DONE:
1088d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		motg->chg_state = USB_CHG_STATE_DETECTED;
1089d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	case USB_CHG_STATE_DETECTED:
1090d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		msm_chg_block_off(motg);
10911d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(phy->dev, "charger = %d\n", motg->chg_type);
1092d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		schedule_work(&motg->sm_work);
1093d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		return;
1094d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	default:
1095d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		return;
1096d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	}
1097d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
1098d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	schedule_delayed_work(&motg->chg_work, delay);
1099d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti}
1100d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti
1101e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti/*
1102e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * We support OTG, Peripheral only and Host only configurations. In case
1103e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1104e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1105e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * enabled when switch is controlled by user and default mode is supplied
1106e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti * by board file, which can be changed by userspace later.
1107e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti */
1108e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic void msm_otg_init_sm(struct msm_otg *motg)
1109e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1110e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg_platform_data *pdata = motg->pdata;
1111e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	u32 otgsc = readl(USB_OTGSC);
1112e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1113e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	switch (pdata->mode) {
1114e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case USB_OTG:
1115e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (pdata->otg_control == OTG_PHY_CONTROL) {
1116e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			if (otgsc & OTGSC_ID)
1117e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				set_bit(ID, &motg->inputs);
1118e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			else
1119e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				clear_bit(ID, &motg->inputs);
1120e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1121e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			if (otgsc & OTGSC_BSV)
1122e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				set_bit(B_SESS_VLD, &motg->inputs);
1123e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			else
1124e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				clear_bit(B_SESS_VLD, &motg->inputs);
1125e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		} else if (pdata->otg_control == OTG_USER_CONTROL) {
1126e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			if (pdata->default_mode == USB_HOST) {
1127e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				clear_bit(ID, &motg->inputs);
1128e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			} else if (pdata->default_mode == USB_PERIPHERAL) {
1129e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				set_bit(ID, &motg->inputs);
1130e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				set_bit(B_SESS_VLD, &motg->inputs);
1131e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			} else {
1132e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				set_bit(ID, &motg->inputs);
1133e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				clear_bit(B_SESS_VLD, &motg->inputs);
1134e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			}
1135e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
1136e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1137e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case USB_HOST:
1138e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		clear_bit(ID, &motg->inputs);
1139e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1140e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case USB_PERIPHERAL:
1141e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		set_bit(ID, &motg->inputs);
1142e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (otgsc & OTGSC_BSV)
1143e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			set_bit(B_SESS_VLD, &motg->inputs);
1144e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		else
1145e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			clear_bit(B_SESS_VLD, &motg->inputs);
1146e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1147e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	default:
1148e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1149e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1150e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1151e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1152e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic void msm_otg_sm_work(struct work_struct *w)
1153e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1154e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
11551d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_otg *otg = motg->phy.otg;
1156e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
11571d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	switch (otg->phy->state) {
1158e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case OTG_STATE_UNDEFINED:
11591d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(otg->phy->dev, "OTG_STATE_UNDEFINED state\n");
11601d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		msm_otg_reset(otg->phy);
1161e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		msm_otg_init_sm(motg);
11621d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		otg->phy->state = OTG_STATE_B_IDLE;
1163e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		/* FALL THROUGH */
1164e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case OTG_STATE_B_IDLE:
11651d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(otg->phy->dev, "OTG_STATE_B_IDLE state\n");
1166e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (!test_bit(ID, &motg->inputs) && otg->host) {
1167e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			/* disable BSV bit */
1168e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
11691d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			msm_otg_start_host(otg->phy, 1);
11701d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			otg->phy->state = OTG_STATE_A_HOST;
1171d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		} else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1172d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			switch (motg->chg_state) {
1173d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			case USB_CHG_STATE_UNDEFINED:
1174d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				msm_chg_detect_work(&motg->chg_work.work);
1175d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				break;
1176d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			case USB_CHG_STATE_DETECTED:
1177d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				switch (motg->chg_type) {
1178d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				case USB_DCP_CHARGER:
1179d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti					msm_otg_notify_charger(motg,
1180d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti							IDEV_CHG_MAX);
1181d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti					break;
1182d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				case USB_CDP_CHARGER:
1183d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti					msm_otg_notify_charger(motg,
1184d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti							IDEV_CHG_MAX);
11851d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus					msm_otg_start_peripheral(otg->phy, 1);
11861d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus					otg->phy->state
11871d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus						= OTG_STATE_B_PERIPHERAL;
1188d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti					break;
1189d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				case USB_SDP_CHARGER:
1190d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti					msm_otg_notify_charger(motg, IUNIT);
11911d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus					msm_otg_start_peripheral(otg->phy, 1);
11921d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus					otg->phy->state
11931d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus						= OTG_STATE_B_PERIPHERAL;
1194d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti					break;
1195d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				default:
1196d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti					break;
1197d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				}
1198d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				break;
1199d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			default:
1200d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti				break;
1201d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			}
1202d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti		} else {
1203d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			/*
1204d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			 * If charger detection work is pending, decrement
1205d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			 * the pm usage counter to balance with the one that
1206d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			 * is incremented in charger detection work.
1207d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			 */
1208d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			if (cancel_delayed_work_sync(&motg->chg_work)) {
12091d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus				pm_runtime_put_sync(otg->phy->dev);
12101d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus				msm_otg_reset(otg->phy);
1211d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			}
1212d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			msm_otg_notify_charger(motg, 0);
1213d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_state = USB_CHG_STATE_UNDEFINED;
1214d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_type = USB_INVALID_CHARGER;
1215e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
12161d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		pm_runtime_put_sync(otg->phy->dev);
1217e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1218e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case OTG_STATE_B_PERIPHERAL:
12191d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(otg->phy->dev, "OTG_STATE_B_PERIPHERAL state\n");
1220e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (!test_bit(B_SESS_VLD, &motg->inputs) ||
1221e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				!test_bit(ID, &motg->inputs)) {
1222d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			msm_otg_notify_charger(motg, 0);
12231d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			msm_otg_start_peripheral(otg->phy, 0);
1224d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_state = USB_CHG_STATE_UNDEFINED;
1225d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti			motg->chg_type = USB_INVALID_CHARGER;
12261d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			otg->phy->state = OTG_STATE_B_IDLE;
12271d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			msm_otg_reset(otg->phy);
1228e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			schedule_work(w);
1229e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
1230e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1231e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case OTG_STATE_A_HOST:
12321d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(otg->phy->dev, "OTG_STATE_A_HOST state\n");
1233e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (test_bit(ID, &motg->inputs)) {
12341d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			msm_otg_start_host(otg->phy, 0);
12351d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			otg->phy->state = OTG_STATE_B_IDLE;
12361d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus			msm_otg_reset(otg->phy);
1237e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			schedule_work(w);
1238e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
1239e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1240e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	default:
1241e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1242e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1243e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1244e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1245e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic irqreturn_t msm_otg_irq(int irq, void *data)
1246e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1247e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg *motg = data;
12481d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
1249e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	u32 otgsc = 0;
1250e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
125187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (atomic_read(&motg->in_lpm)) {
125287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		disable_irq_nosync(irq);
125387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		motg->async_int = 1;
12541d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		pm_runtime_get(phy->dev);
125587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		return IRQ_HANDLED;
125687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	}
125787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
1258e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	otgsc = readl(USB_OTGSC);
1259e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1260e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return IRQ_NONE;
1261e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1262e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
1263e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (otgsc & OTGSC_ID)
1264e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			set_bit(ID, &motg->inputs);
1265e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		else
1266e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			clear_bit(ID, &motg->inputs);
12671d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(phy->dev, "ID set/clear\n");
12681d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		pm_runtime_get_noresume(phy->dev);
1269e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	} else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
1270e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (otgsc & OTGSC_BSV)
1271e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			set_bit(B_SESS_VLD, &motg->inputs);
1272e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		else
1273e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			clear_bit(B_SESS_VLD, &motg->inputs);
12741d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_dbg(phy->dev, "BSV set/clear\n");
12751d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		pm_runtime_get_noresume(phy->dev);
1276e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1277e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1278e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(otgsc, USB_OTGSC);
1279e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	schedule_work(&motg->sm_work);
1280e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return IRQ_HANDLED;
1281e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1282e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1283e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic int msm_otg_mode_show(struct seq_file *s, void *unused)
1284e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1285e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg *motg = s->private;
12861d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_otg *otg = motg->phy.otg;
1287e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
12881d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	switch (otg->phy->state) {
1289e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case OTG_STATE_A_HOST:
1290e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		seq_printf(s, "host\n");
1291e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1292e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case OTG_STATE_B_PERIPHERAL:
1293e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		seq_printf(s, "peripheral\n");
1294e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1295e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	default:
1296e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		seq_printf(s, "none\n");
1297e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1298e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1299e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1300e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return 0;
1301e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1302e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1303e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic int msm_otg_mode_open(struct inode *inode, struct file *file)
1304e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1305e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return single_open(file, msm_otg_mode_show, inode->i_private);
1306e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1307e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1308e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1309e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				size_t count, loff_t *ppos)
1310e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1311e2904ee43c7009e6c4fc18738f15051312f22483Pavankumar Kondeti	struct seq_file *s = file->private_data;
1312e2904ee43c7009e6c4fc18738f15051312f22483Pavankumar Kondeti	struct msm_otg *motg = s->private;
1313e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	char buf[16];
13141d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_otg *otg = motg->phy.otg;
1315e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int status = count;
1316e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	enum usb_mode_type req_mode;
1317e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1318e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	memset(buf, 0x00, sizeof(buf));
1319e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1320e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1321e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		status = -EFAULT;
1322e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto out;
1323e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1324e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1325e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!strncmp(buf, "host", 4)) {
1326e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		req_mode = USB_HOST;
1327e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	} else if (!strncmp(buf, "peripheral", 10)) {
1328e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		req_mode = USB_PERIPHERAL;
1329e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	} else if (!strncmp(buf, "none", 4)) {
1330e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		req_mode = USB_NONE;
1331e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	} else {
1332e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		status = -EINVAL;
1333e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto out;
1334e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1335e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1336e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	switch (req_mode) {
1337e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case USB_NONE:
13381d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		switch (otg->phy->state) {
1339e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		case OTG_STATE_A_HOST:
1340e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		case OTG_STATE_B_PERIPHERAL:
1341e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			set_bit(ID, &motg->inputs);
1342e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			clear_bit(B_SESS_VLD, &motg->inputs);
1343e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			break;
1344e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		default:
1345e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			goto out;
1346e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
1347e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1348e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case USB_PERIPHERAL:
13491d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		switch (otg->phy->state) {
1350e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		case OTG_STATE_B_IDLE:
1351e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		case OTG_STATE_A_HOST:
1352e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			set_bit(ID, &motg->inputs);
1353e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			set_bit(B_SESS_VLD, &motg->inputs);
1354e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			break;
1355e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		default:
1356e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			goto out;
1357e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
1358e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1359e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	case USB_HOST:
13601d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		switch (otg->phy->state) {
1361e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		case OTG_STATE_B_IDLE:
1362e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		case OTG_STATE_B_PERIPHERAL:
1363e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			clear_bit(ID, &motg->inputs);
1364e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			break;
1365e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		default:
1366e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			goto out;
1367e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		}
1368e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		break;
1369e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	default:
1370e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto out;
1371e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1372e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
13731d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	pm_runtime_get_sync(otg->phy->dev);
1374e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	schedule_work(&motg->sm_work);
1375e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetiout:
1376e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return status;
1377e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1378e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1379e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeticonst struct file_operations msm_otg_mode_fops = {
1380e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	.open = msm_otg_mode_open,
1381e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	.read = seq_read,
1382e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	.write = msm_otg_mode_write,
1383e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	.llseek = seq_lseek,
1384e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	.release = single_release,
1385e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti};
1386e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1387e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic struct dentry *msm_otg_dbg_root;
1388e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic struct dentry *msm_otg_dbg_mode;
1389e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1390e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic int msm_otg_debugfs_init(struct msm_otg *motg)
1391e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1392e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
1393e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1394e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
1395e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ENODEV;
1396e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1397e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO | S_IWUSR,
1398e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti				msm_otg_dbg_root, motg, &msm_otg_mode_fops);
1399e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!msm_otg_dbg_mode) {
1400e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		debugfs_remove(msm_otg_dbg_root);
1401e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		msm_otg_dbg_root = NULL;
1402e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ENODEV;
1403e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1404e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1405e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return 0;
1406e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1407e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1408e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic void msm_otg_debugfs_cleanup(void)
1409e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1410e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	debugfs_remove(msm_otg_dbg_mode);
1411e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	debugfs_remove(msm_otg_dbg_root);
1412e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1413e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1414e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic int __init msm_otg_probe(struct platform_device *pdev)
1415e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1416e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	int ret = 0;
1417e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct resource *res;
1418e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg *motg;
14191d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy;
1420e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1421e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	dev_info(&pdev->dev, "msm_otg probe\n");
1422e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!pdev->dev.platform_data) {
1423e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		dev_err(&pdev->dev, "No platform data given. Bailing out\n");
1424e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ENODEV;
1425e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1426e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1427e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
1428e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!motg) {
1429e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
1430e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -ENOMEM;
1431e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1432e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
14331d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	motg->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
14341d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	if (!motg->phy.otg) {
14351d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
14361d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		return -ENOMEM;
14371d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	}
14381d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus
1439e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	motg->pdata = pdev->dev.platform_data;
14401d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	phy = &motg->phy;
14411d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	phy->dev = &pdev->dev;
1442e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1443e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
1444e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (IS_ERR(motg->phy_reset_clk)) {
1445e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
1446e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = PTR_ERR(motg->phy_reset_clk);
1447e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto free_motg;
1448e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1449e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1450e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
1451e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (IS_ERR(motg->clk)) {
1452e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
1453e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = PTR_ERR(motg->clk);
1454e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto put_phy_reset_clk;
1455e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
14560f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	clk_set_rate(motg->clk, 60000000);
14570f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala
14580f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	/*
14590f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	 * If USB Core is running its protocol engine based on CORE CLK,
14600f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	 * CORE CLK  must be running at >55Mhz for correct HSUSB
14610f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	 * operation and USB core cannot tolerate frequency changes on
14620f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	 * CORE CLK. For such USB cores, vote for maximum clk frequency
14630f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	 * on pclk source
14640f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	 */
14650f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	 if (motg->pdata->pclk_src_name) {
14660f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		motg->pclk_src = clk_get(&pdev->dev,
14670f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala			motg->pdata->pclk_src_name);
14680f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		if (IS_ERR(motg->pclk_src))
14690f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala			goto put_clk;
14700f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		clk_set_rate(motg->pclk_src, INT_MAX);
14710f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		clk_enable(motg->pclk_src);
14720f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	} else
14730f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		motg->pclk_src = ERR_PTR(-ENOENT);
14740f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala
1475e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1476e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
1477e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (IS_ERR(motg->pclk)) {
1478e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
1479e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = PTR_ERR(motg->pclk);
14800f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		goto put_pclk_src;
1481e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1482e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1483e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	/*
1484e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * USB core clock is not present on all MSM chips. This
1485e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * clock is introduced to remove the dependency on AXI
1486e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 * bus frequency.
1487e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	 */
1488e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
1489e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (IS_ERR(motg->core_clk))
1490e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		motg->core_clk = NULL;
1491e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1492e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1493e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!res) {
1494e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		dev_err(&pdev->dev, "failed to get platform resource mem\n");
1495e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = -ENODEV;
1496e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto put_core_clk;
1497e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1498e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1499e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	motg->regs = ioremap(res->start, resource_size(res));
1500e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!motg->regs) {
1501e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		dev_err(&pdev->dev, "ioremap failed\n");
1502e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = -ENOMEM;
1503e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto put_core_clk;
1504e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1505e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
1506e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1507e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	motg->irq = platform_get_irq(pdev, 0);
1508e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (!motg->irq) {
1509e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		dev_err(&pdev->dev, "platform_get_irq failed\n");
1510e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = -ENODEV;
1511e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto free_regs;
1512e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1513e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1514e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_enable(motg->clk);
1515e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_enable(motg->pclk);
151611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
151711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	ret = msm_hsusb_init_vddcx(motg, 1);
151811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	if (ret) {
151911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
152011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		goto free_regs;
152111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	}
152211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
152311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	ret = msm_hsusb_ldo_init(motg, 1);
152411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	if (ret) {
152511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
152611aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		goto vddcx_exit;
152711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	}
152811aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	ret = msm_hsusb_ldo_set_mode(1);
152911aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	if (ret) {
153011aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		dev_err(&pdev->dev, "hsusb vreg enable failed\n");
153111aa5c478e743712228ff2da881b85100800c1eeAnji jonnala		goto ldo_exit;
153211aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	}
153311aa5c478e743712228ff2da881b85100800c1eeAnji jonnala
1534e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (motg->core_clk)
1535e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		clk_enable(motg->core_clk);
1536e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1537e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(0, USB_USBINTR);
1538e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	writel(0, USB_OTGSC);
1539e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1540e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
1541d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
1542e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
1543e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti					"msm_otg", motg);
1544e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (ret) {
1545e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		dev_err(&pdev->dev, "request irq failed\n");
1546e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto disable_clks;
1547e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1548e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
15491d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	phy->init = msm_otg_reset;
15501d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	phy->set_power = msm_otg_set_power;
15511d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus
15521d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	phy->io_ops = &msm_otg_io_ops;
1553e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
15541d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	phy->otg->phy = &motg->phy;
15551d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	phy->otg->set_host = msm_otg_set_host;
15561d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	phy->otg->set_peripheral = msm_otg_set_peripheral;
1557e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
15581d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	ret = usb_set_transceiver(&motg->phy);
1559e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (ret) {
15601d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(&pdev->dev, "usb_set_transceiver failed\n");
1561e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		goto free_irq;
1562e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1563e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1564e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	platform_set_drvdata(pdev, motg);
1565e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	device_init_wakeup(&pdev->dev, 1);
1566e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1567e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (motg->pdata->mode == USB_OTG &&
1568e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			motg->pdata->otg_control == OTG_USER_CONTROL) {
1569e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		ret = msm_otg_debugfs_init(motg);
1570e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		if (ret)
1571e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti			dev_dbg(&pdev->dev, "mode debugfs file is"
1572e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti					"not available\n");
1573e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	}
1574e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
157587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	pm_runtime_set_active(&pdev->dev);
157687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	pm_runtime_enable(&pdev->dev);
1577e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
157887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	return 0;
1579e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetifree_irq:
1580e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	free_irq(motg->irq, motg);
1581e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetidisable_clks:
1582e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_disable(motg->pclk);
1583e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_disable(motg->clk);
158411aa5c478e743712228ff2da881b85100800c1eeAnji jonnalaldo_exit:
158511aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	msm_hsusb_ldo_init(motg, 0);
158611aa5c478e743712228ff2da881b85100800c1eeAnji jonnalavddcx_exit:
158711aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	msm_hsusb_init_vddcx(motg, 0);
1588e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetifree_regs:
1589e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	iounmap(motg->regs);
1590e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetiput_core_clk:
1591e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (motg->core_clk)
1592e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		clk_put(motg->core_clk);
1593e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_put(motg->pclk);
15940f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnalaput_pclk_src:
15950f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	if (!IS_ERR(motg->pclk_src)) {
15960f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		clk_disable(motg->pclk_src);
15970f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		clk_put(motg->pclk_src);
15980f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	}
1599e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetiput_clk:
1600e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_put(motg->clk);
1601e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetiput_phy_reset_clk:
1602e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_put(motg->phy_reset_clk);
1603e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetifree_motg:
16041d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	kfree(motg->phy.otg);
1605e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	kfree(motg);
1606e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return ret;
1607e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1608e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1609e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic int __devexit msm_otg_remove(struct platform_device *pdev)
1610e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1611e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	struct msm_otg *motg = platform_get_drvdata(pdev);
16121d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_phy *phy = &motg->phy;
161387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	int cnt = 0;
1614e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
16151d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	if (phy->otg->host || phy->otg->gadget)
1616e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		return -EBUSY;
1617e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1618e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	msm_otg_debugfs_cleanup();
1619d860852e087eed7eadbea64f1a8db9a231c5e9b3Pavankumar Kondeti	cancel_delayed_work_sync(&motg->chg_work);
1620e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	cancel_work_sync(&motg->sm_work);
162187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
16227018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti	pm_runtime_resume(&pdev->dev);
162387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
1624e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	device_init_wakeup(&pdev->dev, 0);
162587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	pm_runtime_disable(&pdev->dev);
1626e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
16271d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	usb_set_transceiver(NULL);
1628e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	free_irq(motg->irq, motg);
1629e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
163087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	/*
163187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * Put PHY in low power mode.
163287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 */
16331d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	ulpi_read(phy, 0x14);
16341d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	ulpi_write(phy, 0x08, 0x09);
163587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
163687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
163787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
163887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		if (readl(USB_PORTSC) & PORTSC_PHCD)
163987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti			break;
164087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		udelay(1);
164187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		cnt++;
164287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	}
164387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
16441d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus		dev_err(phy->dev, "Unable to suspend PHY\n");
164587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
1646e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_disable(motg->pclk);
1647e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_disable(motg->clk);
1648e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (motg->core_clk)
1649e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		clk_disable(motg->core_clk);
16500f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	if (!IS_ERR(motg->pclk_src)) {
16510f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		clk_disable(motg->pclk_src);
16520f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala		clk_put(motg->pclk_src);
16530f73cac8e41723d600c91a0f5b481dc3202f4f82Anji jonnala	}
165411aa5c478e743712228ff2da881b85100800c1eeAnji jonnala	msm_hsusb_ldo_init(motg, 0);
1655e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1656e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	iounmap(motg->regs);
165787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	pm_runtime_set_suspended(&pdev->dev);
1658e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1659e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_put(motg->phy_reset_clk);
1660e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_put(motg->pclk);
1661e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	clk_put(motg->clk);
1662e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	if (motg->core_clk)
1663e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		clk_put(motg->core_clk);
1664e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
16651d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	kfree(motg->phy.otg);
1666e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	kfree(motg);
1667e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1668e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return 0;
1669e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1670e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
167187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti#ifdef CONFIG_PM_RUNTIME
167287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondetistatic int msm_otg_runtime_idle(struct device *dev)
167387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti{
167487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	struct msm_otg *motg = dev_get_drvdata(dev);
16751d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	struct usb_otg *otg = motg->phy.otg;
167687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
167787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	dev_dbg(dev, "OTG runtime idle\n");
167887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
167987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	/*
168087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * It is observed some times that a spurious interrupt
168187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * comes when PHY is put into LPM immediately after PHY reset.
168287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * This 1 sec delay also prevents entering into LPM immediately
168387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * after asynchronous interrupt.
168487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 */
16851d4c9293ae3555f2dcf9f394d1e2a14fd9421c4fHeikki Krogerus	if (otg->phy->state != OTG_STATE_UNDEFINED)
168687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		pm_schedule_suspend(dev, 1000);
168787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
168887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	return -EAGAIN;
168987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti}
169087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
169187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondetistatic int msm_otg_runtime_suspend(struct device *dev)
169287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti{
169387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	struct msm_otg *motg = dev_get_drvdata(dev);
169487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
169587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	dev_dbg(dev, "OTG runtime suspend\n");
169687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	return msm_otg_suspend(motg);
169787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti}
169887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
169987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondetistatic int msm_otg_runtime_resume(struct device *dev)
170087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti{
170187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	struct msm_otg *motg = dev_get_drvdata(dev);
170287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
170387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	dev_dbg(dev, "OTG runtime resume\n");
170487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	return msm_otg_resume(motg);
170587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti}
170687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti#endif
170787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
17087018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti#ifdef CONFIG_PM_SLEEP
170987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondetistatic int msm_otg_pm_suspend(struct device *dev)
171087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti{
171187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	struct msm_otg *motg = dev_get_drvdata(dev);
171287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
171387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	dev_dbg(dev, "OTG PM suspend\n");
171487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	return msm_otg_suspend(motg);
171587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti}
171687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
171787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondetistatic int msm_otg_pm_resume(struct device *dev)
171887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti{
171987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	struct msm_otg *motg = dev_get_drvdata(dev);
172087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	int ret;
172187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
172287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	dev_dbg(dev, "OTG PM resume\n");
172387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
172487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	ret = msm_otg_resume(motg);
172587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	if (ret)
172687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		return ret;
172787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
172887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	/*
172987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * Runtime PM Documentation recommends bringing the
173087c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 * device to full powered state upon resume.
173187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	 */
173287c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	pm_runtime_disable(dev);
173387c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	pm_runtime_set_active(dev);
173487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	pm_runtime_enable(dev);
173587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
173687c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti	return 0;
173787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti}
173887c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti#endif
173987c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
17407018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti#ifdef CONFIG_PM
174187c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondetistatic const struct dev_pm_ops msm_otg_dev_pm_ops = {
17427018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti	SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
17437018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti	SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
17447018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti				msm_otg_runtime_idle)
174587c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti};
17467018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti#endif
174787c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti
1748e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic struct platform_driver msm_otg_driver = {
1749e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	.remove = __devexit_p(msm_otg_remove),
1750e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	.driver = {
1751e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		.name = DRIVER_NAME,
1752e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti		.owner = THIS_MODULE,
17537018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti#ifdef CONFIG_PM
175487c0104af742af2acfcbd685f2b9a40f33770dc0Pavankumar Kondeti		.pm = &msm_otg_dev_pm_ops,
17557018773aca1b46e4f29a8be2c6652448eb603099Pavankumar Kondeti#endif
1756e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	},
1757e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti};
1758e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1759e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic int __init msm_otg_init(void)
1760e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1761e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
1762e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1763e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1764e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetistatic void __exit msm_otg_exit(void)
1765e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti{
1766e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti	platform_driver_unregister(&msm_otg_driver);
1767e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti}
1768e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1769e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetimodule_init(msm_otg_init);
1770e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondetimodule_exit(msm_otg_exit);
1771e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar Kondeti
1772e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar KondetiMODULE_LICENSE("GPL v2");
1773e0c201f339fe7fc38d1b0f6f4755ff627686c7e0Pavankumar KondetiMODULE_DESCRIPTION("MSM USB transceiver driver");
1774