From 5bf7f673993fc1da6a5be602d1f26b03af7838b3 Mon Sep 17 00:00:00 2001 From: Rakesh Bodla Date: Thu, 28 Jul 2011 09:51:11 +0530 Subject: 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 Tested-by: Varun Colbert --- arch/arm/mach-tegra/include/mach/usb_phy.h | 2 + arch/arm/mach-tegra/usb_phy.c | 62 +++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) (limited to 'arch') 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) { -- cgit v1.2.3