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