diff options
author | Rakesh Bodla <rbodla@nvidia.com> | 2011-07-22 11:50:40 +0530 |
---|---|---|
committer | Manish Tuteja <mtuteja@nvidia.com> | 2011-07-25 02:31:34 -0700 |
commit | 69c083d495e1f187654c5a1bcd58569e54bf985b (patch) | |
tree | 1fb3f0f943f6ffa03d2e9aee77703c965ac1a088 | |
parent | be13b88a2cb2f898d02d266041e1f2ae0a9b259b (diff) |
tegra: usb: phy: USB charger detection support
USB PHY related charger detection logic is
implemented.
Bug 819334
Change-Id: Ica7e66509d52d787cc5c25434b45534176bc8dc7
Reviewed-on: http://git-master/r/42298
Reviewed-by: Rakesh Bodla <rbodla@nvidia.com>
Tested-by: Rakesh Bodla <rbodla@nvidia.com>
Reviewed-by: Hanumanth Venkateswa Moganty <vmoganty@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/include/mach/usb_phy.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/usb_phy.c | 54 |
2 files changed, 56 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h index 0ff8f5545d31..609134c4ff82 100644 --- a/arch/arm/mach-tegra/include/mach/usb_phy.h +++ b/arch/arm/mach-tegra/include/mach/usb_phy.h @@ -126,6 +126,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 ee17dffc3d8c..0dc14abc3fa4 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -76,6 +76,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) @@ -163,6 +168,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_SPARE_CFG0 0x834 #define FUSE_SETUP_SEL (1 << 3) @@ -225,6 +232,10 @@ #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; @@ -1464,6 +1475,49 @@ 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_is_ulpi(phy)) { + /* 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) { |