summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRakesh Bodla <rbodla@nvidia.com>2011-07-28 09:51:11 +0530
committerVarun Colbert <vcolbert@nvidia.com>2011-08-09 11:33:07 -0700
commit5bf7f673993fc1da6a5be602d1f26b03af7838b3 (patch)
treedb5238da8916597461cdc950b1419ac3fce27c03 /arch
parent1588df7c439629757e3145a78c3c60b9ca13f25a (diff)
tegra: usb: phy: USB charger detection support
USB PHY related charger detection logic is implemented. Bug 819334 Reviewed-on: http://git-master/r/42298 (cherry picked from commit 69c083d495e1f187654c5a1bcd58569e54bf985b) Change-Id: Iaea04cab1a768df213b392de3603552581cc3a33 Reviewed-on: http://git-master/r/43518 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/include/mach/usb_phy.h2
-rw-r--r--arch/arm/mach-tegra/usb_phy.c62
2 files changed, 63 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
index bad62c68df71..2c81706250a8 100644
--- a/arch/arm/mach-tegra/include/mach/usb_phy.h
+++ b/arch/arm/mach-tegra/include/mach/usb_phy.h
@@ -137,6 +137,8 @@ int tegra_usb_phy_bus_idle(struct tegra_usb_phy *phy);
bool tegra_usb_phy_is_device_connected(struct tegra_usb_phy *phy);
+bool tegra_usb_phy_charger_detect(struct tegra_usb_phy *phy);
+
int __init tegra_usb_phy_init(struct usb_phy_plat_data *pdata, int size);
#endif /* __MACH_USB_PHY_H */
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index 48feb5adf6e4..5625d36dc70d 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -82,6 +82,11 @@
#define USB_SUSP_SET (1 << 14)
#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
+#define USB_PHY_VBUS_WAKEUP_ID 0x408
+#define VDAT_DET_INT_EN (1 << 16)
+#define VDAT_DET_CHG_DET (1 << 17)
+#define VDAT_DET_STS (1 << 18)
+
#define USB1_LEGACY_CTRL 0x410
#define USB1_NO_LEGACY_MODE (1 << 0)
#define USB1_VBUS_SENSE_CTL_MASK (3 << 1)
@@ -139,6 +144,8 @@
#define UTMIP_BAT_CHRG_CFG0 0x830
#define UTMIP_PD_CHRG (1 << 0)
+#define UTMIP_ON_SINK_EN (1 << 2)
+#define UTMIP_OP_SRC_EN (1 << 3)
#define UTMIP_XCVR_CFG1 0x838
#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
@@ -231,6 +238,11 @@
#define ULPI_PADS_RESET (1 << 23)
#define ULPI_PADS_CLKEN_RESET (1 << 24)
+#define USB_PHY_VBUS_WAKEUP_ID 0x408
+#define VDAT_DET_INT_EN (1 << 16)
+#define VDAT_DET_CHG_DET (1 << 17)
+#define VDAT_DET_STS (1 << 18)
+
#define USB1_LEGACY_CTRL 0x410
#define USB1_NO_LEGACY_MODE (1 << 0)
#define USB1_VBUS_SENSE_CTL_MASK (3 << 1)
@@ -284,6 +296,8 @@
#define UTMIP_BAT_CHRG_CFG0 0x830
#define UTMIP_PD_CHRG (1 << 0)
+#define UTMIP_ON_SINK_EN (1 << 2)
+#define UTMIP_OP_SRC_EN (1 << 3)
#define UTMIP_XCVR_CFG1 0x838
#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
@@ -404,7 +418,9 @@
#define UHSIC_SPARE_CFG0 0x82c
-
+/* These values (in milli second) are taken from the battery charging spec */
+#define TDP_SRC_ON_MS 100
+#define TDPSRC_CON_MS 40
static DEFINE_SPINLOCK(utmip_pad_lock);
static int utmip_pad_count;
@@ -2036,6 +2052,50 @@ bool tegra_usb_phy_is_device_connected(struct tegra_usb_phy *phy)
return true;
}
+bool tegra_usb_phy_charger_detect(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ bool status;
+
+ if (phy->usb_phy_type != TEGRA_USB_PHY_TYPE_UTMIP)
+ {
+ /* Charger detection is not there for ULPI
+ * return Charger not available */
+ return false;
+ }
+
+ /* Enable charger detection logic */
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+ /* Source should be on for 100 ms as per USB charging spec */
+ msleep(TDP_SRC_ON_MS);
+
+ val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
+ /* If charger is not connected disable the interrupt */
+ val &= ~VDAT_DET_INT_EN;
+ val |= VDAT_DET_CHG_DET;
+ writel(val,base + USB_PHY_VBUS_WAKEUP_ID);
+
+ val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
+ if (val & VDAT_DET_STS)
+ status = true;
+ else
+ status = false;
+
+ /* Disable charger detection logic */
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val &= ~(UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN);
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+ /* Delay of 40 ms before we pull the D+ as per battery charger spec */
+ msleep(TDPSRC_CON_MS);
+
+ return status;
+}
+
int __init tegra_usb_phy_init(struct usb_phy_plat_data *pdata, int size)
{
if (pdata) {