diff options
author | Rakesh Bodla <rbodla@nvidia.com> | 2011-07-28 09:51:11 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-08-09 11:33:07 -0700 |
commit | 5bf7f673993fc1da6a5be602d1f26b03af7838b3 (patch) | |
tree | db5238da8916597461cdc950b1419ac3fce27c03 /arch | |
parent | 1588df7c439629757e3145a78c3c60b9ca13f25a (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.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/usb_phy.c | 62 |
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) { |