* [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
@ 2011-04-28 8:01 Pavankumar Kondeti
2011-04-28 8:01 ` [PATCH 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
` (9 more replies)
0 siblings, 10 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-28 8:01 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
ITC (Interrupt Threshold Control) field is to set the maximum rate at which
the device controller will issue interrupts. The maximum interrupt interval
is measured in micro frames. Valid values are 0, 1, 2, 4, 8, 16, 32, 64.
The default value is 8 micro frames. Set ITC to zero for MSM to gain
performance.
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/gadget/ci13xxx_msm.c | 3 ++-
drivers/usb/gadget/ci13xxx_udc.c | 11 +++++++++++
drivers/usb/gadget/ci13xxx_udc.h | 3 +++
3 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 139ac94..aa8319b 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -64,7 +64,8 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
- CI13XXX_DISABLE_STREAMING,
+ CI13XXX_DISABLE_STREAMING |
+ CI13XXX_ZERO_ITC,
.notify_event = ci13xxx_msm_notify_event,
};
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index e09178b..bd1a059 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -318,6 +318,17 @@ static int hw_device_reset(struct ci13xxx *udc)
hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
+ /*
+ * ITC (Interrupt Threshold Control) field is to set the maximum
+ * rate at which the device controller will issue interrupts.
+ * The maximum interrupt interval measured in micro frames.
+ * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
+ * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
+ * can be set to lesser value to gain performance.
+ */
+ if (udc->udc_driver->flags && CI13XXX_ZERO_ITC)
+ hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
+
if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
pr_err("cannot enter in device mode");
pr_err("lpm = %i", hw_bank.lpm);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 2370777..a230325 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -108,6 +108,7 @@ struct ci13xxx_udc_driver {
#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
#define CI13XXX_PULLUP_ON_VBUS BIT(2)
#define CI13XXX_DISABLE_STREAMING BIT(3)
+#define CI13XXX_ZERO_ITC BIT(4)
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_STOPPED_EVENT 1
@@ -189,6 +190,8 @@ struct ci13xxx {
#define USBMODE_CM_HOST (0x03UL << 0)
#define USBMODE_SLOM BIT(3)
#define USBMODE_SDIS BIT(4)
+#define USBCMD_ITC(n) (n << 16) /* n = 0, 1, 2, 4, 8, 16, 32, 64 */
+#define USBCMD_ITC_MASK (0xFF << 16)
/* ENDPTCTRL */
#define ENDPTCTRL_RXS BIT(0)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 2/5] USB: OTG: vote for dayatona fabric clock
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
@ 2011-04-28 8:01 ` Pavankumar Kondeti
2011-04-28 8:01 ` [PATCH 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
` (8 subsequent siblings)
9 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-28 8:01 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
HSUSB core clock is derived from daytona fabric clock and for
HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
cannot tolerate daytona fabric clock change in the middle of HSUSB
operational, vote for maximum Daytona fabric clock
while usb is operational
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 37 +++++++++++++++++++++++++++++++++++--
include/linux/usb/msm_hsusb.h | 7 +++++--
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 2965986..cfbb606 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -324,6 +324,9 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src))
+ clk_disable(motg->pclk_src);
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -347,6 +350,9 @@ static int msm_otg_resume(struct msm_otg *motg)
if (!atomic_read(&motg->in_lpm))
return 0;
+ if (!IS_ERR(motg->pclk_src))
+ clk_enable(motg->pclk_src);
+
clk_enable(motg->pclk);
clk_enable(motg->clk);
if (motg->core_clk)
@@ -862,12 +868,31 @@ static int __init msm_otg_probe(struct platform_device *pdev)
ret = PTR_ERR(motg->clk);
goto put_phy_reset_clk;
}
+ clk_set_rate(motg->clk, 60000000);
+
+ /*
+ * If USB Core is running its protocol engine based on CORE CLK,
+ * CORE CLK must be running at >55Mhz for correct HSUSB
+ * operation and USB core cannot tolerate frequency changes on
+ * CORE CLK. For such USB cores, vote for maximum clk frequency
+ * on pclk source
+ */
+ if (motg->pdata->pclk_src_name) {
+ motg->pclk_src = clk_get(&pdev->dev,
+ motg->pdata->pclk_src_name);
+ if (IS_ERR(motg->pclk_src))
+ goto put_clk;
+ clk_set_rate(motg->pclk_src, INT_MAX);
+ clk_enable(motg->pclk_src);
+ } else
+ motg->pclk_src = ERR_PTR(-ENOENT);
+
motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
if (IS_ERR(motg->pclk)) {
dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
ret = PTR_ERR(motg->pclk);
- goto put_clk;
+ goto put_pclk_src;
}
/*
@@ -954,7 +979,11 @@ free_regs:
put_core_clk:
if (motg->core_clk)
clk_put(motg->core_clk);
- clk_put(motg->pclk);
+put_pclk_src:
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
put_clk:
clk_put(motg->clk);
put_phy_reset_clk:
@@ -1004,6 +1033,10 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->clk);
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 3657403..31ef185 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -64,7 +64,8 @@ enum otg_control_type {
* @otg_control: OTG switch controlled by user/Id pin
* @default_mode: Default operational mode. Applicable only if
* OTG switch is controller by user.
- *
+ * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k
+ * dfab_usb_hs_clk in case of 8660 and 8960.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -74,6 +75,7 @@ struct msm_otg_platform_data {
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
void (*setup_gpio)(enum usb_otg_state state);
+ char *pclk_src_name;
};
/**
@@ -83,6 +85,7 @@ struct msm_otg_platform_data {
* @irq: IRQ number assigned for HSUSB controller.
* @clk: clock struct of usb_hs_clk.
* @pclk: clock struct of usb_hs_pclk.
+ * @pclk_src: pclk source for voting.
* @phy_reset_clk: clock struct of usb_phy_clk.
* @core_clk: clock struct of usb_hs_core_clk.
* @regs: ioremapped register base address.
@@ -90,7 +93,6 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
- *
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -98,6 +100,7 @@ struct msm_otg {
int irq;
struct clk *clk;
struct clk *pclk;
+ struct clk *pclk_src;
struct clk *phy_reset_clk;
struct clk *core_clk;
void __iomem *regs;
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 3/5] USB: OTG: msm: Implement charger detection
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
2011-04-28 8:01 ` [PATCH 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
@ 2011-04-28 8:01 ` Pavankumar Kondeti
2011-04-28 8:01 ` [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
` (7 subsequent siblings)
9 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-28 8:01 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, Pavankumar Kondeti
Implement good battery algorithm defined in the battery charging V1.2 spec
for detecting different charging ports. USB hardware is put into low power
mode when connected to a dedicated charging port. vbus_draw and set_power
methods are implemented for determining the allowed current from Host in
different states (un-configured/suspend/configured).
The charger block is implemented using vendor specific registers and the
PHY used in MSM8960(28nm PHY) different from older targets like MSM8x60
and MSM7x30(45nm PHY). The PHY vendor and product id registers are not
implemented in the above chipsets. Hence PHY type is passed via platform
data.
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/gadget/ci13xxx_udc.c | 10 +
drivers/usb/otg/msm_otg.c | 380 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 72 +++++++-
3 files changed, 457 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index bd1a059..391f13e 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2508,6 +2508,15 @@ out:
return ret;
}
+static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+ struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+
+ if (udc->transceiver)
+ return otg_set_power(udc->transceiver, mA);
+ return -ENOTSUPP;
+}
+
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
@@ -2516,6 +2525,7 @@ out:
static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci13xxx_vbus_session,
.wakeup = ci13xxx_wakeup,
+ .vbus_draw = ci13xxx_vbus_draw,
};
/**
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index cfbb606..526a650 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -409,6 +409,33 @@ skip_phy_resume:
}
#endif
+static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
+{
+ if (motg->cur_power == mA)
+ return;
+
+ /* TODO: Notify PMIC about available current */
+ dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
+ motg->cur_power = mA;
+}
+
+static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+ struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+ /*
+ * Gadget driver uses set_power method to notify about the
+ * available current based on suspend/configured states.
+ *
+ * IDEV_CHG can be drawn irrespective of suspend/un-configured
+ * states when CDP/ACA is connected.
+ */
+ if (motg->chg_type == USB_SDP_CHARGER)
+ msm_otg_notify_charger(motg, mA);
+
+ return 0;
+}
+
static void msm_otg_start_host(struct otg_transceiver *otg, int on)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -563,6 +590,306 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg,
return 0;
}
+static bool msm_chg_check_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* put it in host mode for enabling D- source */
+ chg_det &= ~(1 << 2);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DM as current source, DP as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x8, 0x85);
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DP as current source, DM as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 line_state;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x15);
+ ret = !(line_state & 1);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x87);
+ ret = line_state & 2;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_disable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ chg_det &= ~(1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ ulpi_write(otg, 0x10, 0x86);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_enable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn on D+ current source */
+ chg_det |= (1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Data contact detection enable */
+ ulpi_write(otg, 0x10, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_on(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ /* put the controller in non-driving mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ udelay(100);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_off(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ break;
+ default:
+ break;
+ }
+
+ /* put the controller in normal mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+}
+
+#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
+#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
+static void msm_chg_detect_work(struct work_struct *w)
+{
+ struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
+ struct otg_transceiver *otg = &motg->otg;
+ bool is_dcd, tmout, vout;
+ unsigned long delay;
+
+ dev_dbg(otg->dev, "chg detection work\n");
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ pm_runtime_get_sync(otg->dev);
+ msm_chg_block_on(motg);
+ msm_chg_enable_dcd(motg);
+ motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
+ motg->dcd_retries = 0;
+ delay = MSM_CHG_DCD_POLL_TIME;
+ break;
+ case USB_CHG_STATE_WAIT_FOR_DCD:
+ is_dcd = msm_chg_check_dcd(motg);
+ tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
+ if (is_dcd || tmout) {
+ msm_chg_disable_dcd(motg);
+ msm_chg_enable_primary_det(motg);
+ delay = MSM_CHG_PRIMARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_DCD_DONE;
+ } else {
+ delay = MSM_CHG_DCD_POLL_TIME;
+ }
+ break;
+ case USB_CHG_STATE_DCD_DONE:
+ vout = msm_chg_check_primary_det(motg);
+ if (vout) {
+ msm_chg_enable_secondary_det(motg);
+ delay = MSM_CHG_SECONDARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
+ } else {
+ motg->chg_type = USB_SDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ delay = 0;
+ }
+ break;
+ case USB_CHG_STATE_PRIMARY_DONE:
+ vout = msm_chg_check_secondary_det(motg);
+ if (vout)
+ motg->chg_type = USB_DCP_CHARGER;
+ else
+ motg->chg_type = USB_CDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
+ /* fall through */
+ case USB_CHG_STATE_SECONDARY_DONE:
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ case USB_CHG_STATE_DETECTED:
+ msm_chg_block_off(motg);
+ dev_dbg(otg->dev, "charger = %d\n", motg->chg_type);
+ schedule_work(&motg->sm_work);
+ return;
+ default:
+ return;
+ }
+
+ schedule_delayed_work(&motg->chg_work, delay);
+}
+
/*
* We support OTG, Peripheral only and Host only configurations. In case
* of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
@@ -633,9 +960,48 @@ static void msm_otg_sm_work(struct work_struct *w)
writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
msm_otg_start_host(otg, 1);
otg->state = OTG_STATE_A_HOST;
- } else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) {
- msm_otg_start_peripheral(otg, 1);
- otg->state = OTG_STATE_B_PERIPHERAL;
+ } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ msm_chg_detect_work(&motg->chg_work.work);
+ break;
+ case USB_CHG_STATE_DETECTED:
+ switch (motg->chg_type) {
+ case USB_DCP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ break;
+ case USB_CDP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ case USB_SDP_CHARGER:
+ msm_otg_notify_charger(motg, IUNIT);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ /*
+ * If charger detection work is pending, decrement
+ * the pm usage counter to balance with the one that
+ * is incremented in charger detection work.
+ */
+ if (cancel_delayed_work_sync(&motg->chg_work)) {
+ pm_runtime_put_sync(otg->dev);
+ msm_otg_reset(otg);
+ }
+ msm_otg_notify_charger(motg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
}
pm_runtime_put_sync(otg->dev);
break;
@@ -643,7 +1009,10 @@ static void msm_otg_sm_work(struct work_struct *w)
dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
if (!test_bit(B_SESS_VLD, &motg->inputs) ||
!test_bit(ID, &motg->inputs)) {
+ msm_otg_notify_charger(motg, 0);
msm_otg_start_peripheral(otg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
otg->state = OTG_STATE_B_IDLE;
msm_otg_reset(otg);
schedule_work(w);
@@ -935,6 +1304,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
writel(0, USB_OTGSC);
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+ INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
"msm_otg", motg);
if (ret) {
@@ -945,6 +1315,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
otg->init = msm_otg_reset;
otg->set_host = msm_otg_set_host;
otg->set_peripheral = msm_otg_set_peripheral;
+ otg->set_power = msm_otg_set_power;
otg->io_ops = &msm_otg_io_ops;
@@ -1003,6 +1374,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
return -EBUSY;
msm_otg_debugfs_cleanup();
+ cancel_delayed_work_sync(&motg->chg_work);
cancel_work_sync(&motg->sm_work);
pm_runtime_resume(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 31ef185..00311fe 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -54,6 +54,64 @@ enum otg_control_type {
};
/**
+ * PHY used in
+ *
+ * INVALID_PHY Unsupported PHY
+ * CI_45NM_INTEGRATED_PHY Chipidea 45nm integrated PHY
+ * SNPS_28NM_INTEGRATED_PHY Synopsis 28nm integrated PHY
+ *
+ */
+enum msm_usb_phy_type {
+ INVALID_PHY = 0,
+ CI_45NM_INTEGRATED_PHY,
+ SNPS_28NM_INTEGRATED_PHY,
+};
+
+#define IDEV_CHG_MAX 1500
+#define IUNIT 100
+
+/**
+ * Different states involved in USB charger detection.
+ *
+ * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
+ * process is not yet started.
+ * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
+ * USB_CHG_STATE_DCD_DONE Data pin contact is detected.
+ * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
+ * between SDP and DCP/CDP).
+ * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
+ * between DCP and CDP).
+ * USB_CHG_STATE_DETECTED USB charger type is determined.
+ *
+ */
+enum usb_chg_state {
+ USB_CHG_STATE_UNDEFINED = 0,
+ USB_CHG_STATE_WAIT_FOR_DCD,
+ USB_CHG_STATE_DCD_DONE,
+ USB_CHG_STATE_PRIMARY_DONE,
+ USB_CHG_STATE_SECONDARY_DONE,
+ USB_CHG_STATE_DETECTED,
+};
+
+/**
+ * USB charger types
+ *
+ * USB_INVALID_CHARGER Invalid USB charger.
+ * USB_SDP_CHARGER Standard downstream port. Refers to a downstream port
+ * on USB2.0 compliant host/hub.
+ * USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
+ * USB_CDP_CHARGER Charging downstream port. Enumeration can happen and
+ * IDEV_CHG_MAX can be drawn irrespective of USB state.
+ *
+ */
+enum usb_chg_type {
+ USB_INVALID_CHARGER = 0,
+ USB_SDP_CHARGER,
+ USB_DCP_CHARGER,
+ USB_CDP_CHARGER,
+};
+
+/**
* struct msm_otg_platform_data - platform device data
* for msm_otg driver.
* @phy_init_seq: PHY configuration sequence. val, reg pairs
@@ -74,6 +132,7 @@ struct msm_otg_platform_data {
enum usb_mode_type mode;
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
+ enum msm_usb_phy_type phy_type;
void (*setup_gpio)(enum usb_otg_state state);
char *pclk_src_name;
};
@@ -93,6 +152,12 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
+ * @cur_power: The amount of mA available from downstream port.
+ * @chg_work: Charger detection work.
+ * @chg_state: The state of charger detection process.
+ * @chg_type: The type of charger attached.
+ * @dcd_retires: The retry count used to track Data contact
+ * detection process.
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -110,6 +175,11 @@ struct msm_otg {
struct work_struct sm_work;
atomic_t in_lpm;
int async_int;
+ unsigned cur_power;
+ struct delayed_work chg_work;
+ enum usb_chg_state chg_state;
+ enum usb_chg_type chg_type;
+ u8 dcd_retries;
};
#endif
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
2011-04-28 8:01 ` [PATCH 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
2011-04-28 8:01 ` [PATCH 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
@ 2011-04-28 8:01 ` Pavankumar Kondeti
2011-04-29 10:14 ` Sergei Shtylyov
2011-04-28 8:01 ` [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
` (6 subsequent siblings)
9 siblings, 1 reply; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-28 8:01 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 194 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 193 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 526a650..425418d 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -38,6 +38,7 @@
#include <linux/usb/hcd.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
@@ -45,6 +46,175 @@
#define DRIVER_NAME "msm_otg"
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
+
+#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
+#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
+#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
+#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
+#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
+#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
+#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+
+static struct regulator *hsusb_3p3;
+static struct regulator *hsusb_1p8;
+static struct regulator *hsusb_vddcx;
+
+static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
+{
+ int ret = 0;
+
+ if (init) {
+ hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+ if (IS_ERR(hsusb_vddcx)) {
+ dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+ return PTR_ERR(hsusb_vddcx);
+ }
+
+ ret = regulator_set_voltage(hsusb_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage"
+ "for hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ return ret;
+ }
+
+ ret = regulator_enable(hsusb_vddcx);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ }
+ } else {
+ ret = regulator_set_voltage(hsusb_vddcx, 0,
+ USB_PHY_VDD_DIG_VOL_MIN);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage"
+ "for hsusb vddcx\n");
+ return ret;
+ }
+ ret = regulator_disable(hsusb_vddcx);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
+ return ret;
+ }
+
+ regulator_put(hsusb_vddcx);
+ }
+
+ return ret;
+}
+
+static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
+{
+ int rc = 0;
+
+ if (init) {
+ hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
+ if (IS_ERR(hsusb_3p3)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
+ return PTR_ERR(hsusb_3p3);
+ }
+
+ rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
+ USB_PHY_3P3_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level for"
+ "hsusb 3p3\n");
+ goto put_3p3;
+ }
+ rc = regulator_enable(hsusb_3p3);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
+ goto put_3p3_lpm;
+ }
+ hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
+ if (IS_ERR(hsusb_1p8)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
+ rc = PTR_ERR(hsusb_1p8);
+ goto put_3p3_lpm;
+ }
+ rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
+ USB_PHY_1P8_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level for"
+ "hsusb 1p8\n");
+ goto put_1p8;
+ }
+ rc = regulator_enable(hsusb_1p8);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
+ goto disable_1p8;
+ }
+
+ return 0;
+ }
+
+disable_1p8:
+ regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
+ regulator_disable(hsusb_1p8);
+put_1p8:
+ regulator_put(hsusb_1p8);
+put_3p3_lpm:
+ regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
+put_3p3:
+ regulator_put(hsusb_3p3);
+ return rc;
+}
+
+static int msm_hsusb_ldo_set_mode(int on)
+{
+ int ret = 0;
+
+ if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
+ pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
+ pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (on) {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator:"
+ "HSUSB_1p8\n", __func__);
+ return ret;
+ }
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator:"
+ "HSUSB_3p3\n", __func__);
+ regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ return ret;
+ }
+ } else {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator:"
+ "HSUSB_1p8\n", __func__);
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator:"
+ "HSUSB_3p3\n", __func__);
+ }
+
+ pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+ return ret < 0 ? ret : 0;
+}
+
static int ulpi_read(struct otg_transceiver *otg, u32 reg)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -353,7 +523,6 @@ static int msm_otg_resume(struct msm_otg *motg)
if (!IS_ERR(motg->pclk_src))
clk_enable(motg->pclk_src);
- clk_enable(motg->pclk);
clk_enable(motg->clk);
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -1297,6 +1466,24 @@ static int __init msm_otg_probe(struct platform_device *pdev)
clk_enable(motg->clk);
clk_enable(motg->pclk);
+
+ ret = msm_hsusb_init_vddcx(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+ goto free_regs;
+ }
+
+ ret = msm_hsusb_ldo_init(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+ goto free_config_vddcx;
+ }
+ ret = msm_hsusb_ldo_set_mode(1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+ goto free_ldo_init;
+ }
+
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -1345,6 +1532,10 @@ free_irq:
disable_clks:
clk_disable(motg->pclk);
clk_disable(motg->clk);
+free_ldo_init:
+ msm_hsusb_ldo_init(motg, 0);
+free_config_vddcx:
+ msm_hsusb_init_vddcx(motg, 0);
free_regs:
iounmap(motg->regs);
put_core_clk:
@@ -1409,6 +1600,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->pclk_src);
clk_put(motg->pclk_src);
}
+ msm_hsusb_ldo_init(motg, 0);
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
` (2 preceding siblings ...)
2011-04-28 8:01 ` [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
@ 2011-04-28 8:01 ` Pavankumar Kondeti
2011-04-28 14:49 ` Sergei Shtylyov
2011-04-28 12:18 ` [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Sergei Shtylyov
` (5 subsequent siblings)
9 siblings, 1 reply; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-28 8:01 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, Pavankumar Kondeti
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 64 ++++++++++++++++++++++++++++++++------
include/linux/usb/msm_hsusb_hw.h | 2 +
2 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 425418d..fe040a2 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -167,6 +167,32 @@ put_3p3:
return rc;
}
+#ifdef CONFIG_PM_SLEEP
+static int usb_phy_susp_dig_vol = 500000;
+static int msm_hsusb_config_vddcx(int high)
+{
+ int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+ int min_vol;
+ int ret;
+
+ if (high)
+ min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+ else
+ min_vol = usb_phy_susp_dig_vol;
+
+ ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+ if (ret) {
+ pr_err("%s: unable to set the voltage for regulator"
+ "HSUSB_VDDCX\n", __func__);
+ return ret;
+ }
+
+ pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+ return ret;
+}
+#endif
+
static int msm_hsusb_ldo_set_mode(int on)
{
int ret = 0;
@@ -438,27 +464,28 @@ static int msm_otg_suspend(struct msm_otg *motg)
disable_irq(motg->irq);
/*
+ * Chipidea 45-nm PHY suspend sequence:
+ *
* Interrupt Latch Register auto-clear feature is not present
* in all PHY versions. Latch register is clear on read type.
* Clear latch register to avoid spurious wakeup from
* low power mode (LPM).
- */
- ulpi_read(otg, 0x14);
-
- /*
+ *
* PHY comparators are disabled when PHY enters into low power
* mode (LPM). Keep PHY comparators ON in LPM only when we expect
* VBUS/Id notifications from USB PHY. Otherwise turn off USB
* PHY comparators. This save significant amount of power.
- */
- if (pdata->otg_control == OTG_PHY_CONTROL)
- ulpi_write(otg, 0x01, 0x30);
-
- /*
+ *
* PLL is not turned off when PHY enters into low power mode (LPM).
* Disable PLL for maximum power savings.
*/
- ulpi_write(otg, 0x08, 0x09);
+
+ if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
+ ulpi_read(otg, 0x14);
+ if (pdata->otg_control == OTG_PHY_CONTROL)
+ ulpi_write(otg, 0x01, 0x30);
+ ulpi_write(otg, 0x08, 0x09);
+ }
/*
* PHY may take some time or even fail to enter into low power
@@ -489,6 +516,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
*/
writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->phy_type == OTG_PMIC_CONTROL)
+ writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
+
clk_disable(motg->pclk);
clk_disable(motg->clk);
if (motg->core_clk)
@@ -497,6 +528,12 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (!IS_ERR(motg->pclk_src))
clk_disable(motg->pclk_src);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->phy_type == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_enable(0);
+ msm_hsusb_config_vddcx(0);
+ }
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -527,6 +564,13 @@ static int msm_otg_resume(struct msm_otg *motg)
if (motg->core_clk)
clk_enable(motg->core_clk);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->phy_type == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_enable(1);
+ msm_hsusb_config_vddcx(1);
+ writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
+ }
+
temp = readl(USB_USBCMD);
temp &= ~ASYNC_INTR_CTRL;
temp &= ~ULPI_STP_CTRL;
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 7d1babb..6e97a2d 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
#define USB_PORTSC (MSM_USB_BASE + 0x0184)
#define USB_OTGSC (MSM_USB_BASE + 0x01A4)
#define USB_USBMODE (MSM_USB_BASE + 0x01A8)
+#define USB_PHY_CTRL (MSM_USB_BASE + 0x0240)
#define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148)
@@ -42,6 +43,7 @@
#define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */
#define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */
+#define PHY_RETEN (1 << 1) /* PHY retention enable/disable */
/* OTG definitions */
#define OTGSC_INTSTS_MASK (0x7f << 16)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
` (3 preceding siblings ...)
2011-04-28 8:01 ` [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
@ 2011-04-28 12:18 ` Sergei Shtylyov
2011-04-29 5:16 ` Pavan Kondeti
2011-04-29 5:22 ` Pavankumar Kondeti
` (4 subsequent siblings)
9 siblings, 1 reply; 45+ messages in thread
From: Sergei Shtylyov @ 2011-04-28 12:18 UTC (permalink / raw)
To: Pavankumar Kondeti; +Cc: greg, linux-usb, linux-arm-msm, Anji jonnala
Hello.
On 28-04-2011 12:01, Pavankumar Kondeti wrote:
> From: Anji jonnala <anjir@codeaurora.org>
> ITC (Interrupt Threshold Control) field is to set the maximum rate at which
> the device controller will issue interrupts. The maximum interrupt interval
> is measured in micro frames. Valid values are 0, 1, 2, 4, 8, 16, 32, 64.
> The default value is 8 micro frames. Set ITC to zero for MSM to gain
> performance.
> Signed-off-by: Anji jonnala<anjir@codeaurora.org>
> Signed-off-by: Pavankumar Kondeti<pkondeti@codeaurora.org>
> ---
> drivers/usb/gadget/ci13xxx_msm.c | 3 ++-
> drivers/usb/gadget/ci13xxx_udc.c | 11 +++++++++++
> drivers/usb/gadget/ci13xxx_udc.h | 3 +++
> 3 files changed, 16 insertions(+), 1 deletions(-)
> diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
> index e09178b..bd1a059 100644
> --- a/drivers/usb/gadget/ci13xxx_udc.c
> +++ b/drivers/usb/gadget/ci13xxx_udc.c
> @@ -318,6 +318,17 @@ static int hw_device_reset(struct ci13xxx *udc)
> hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
> hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW>= 2.3 */
>
> + /*
> + * ITC (Interrupt Threshold Control) field is to set the maximum
> + * rate at which the device controller will issue interrupts.
> + * The maximum interrupt interval measured in micro frames.
> + * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
> + * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
> + * can be set to lesser value to gain performance.
> + */
> + if (udc->udc_driver->flags && CI13XXX_ZERO_ITC)
I think you meant bitwise AND (&) here.
WBR, Sergei
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960
2011-04-28 8:01 ` [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
@ 2011-04-28 14:49 ` Sergei Shtylyov
2011-04-29 5:20 ` Pavan Kondeti
0 siblings, 1 reply; 45+ messages in thread
From: Sergei Shtylyov @ 2011-04-28 14:49 UTC (permalink / raw)
To: Pavankumar Kondeti; +Cc: greg, linux-usb, linux-arm-msm
Hello.
Pavankumar Kondeti wrote:
> Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
[...]
> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
> index 425418d..fe040a2 100644
> --- a/drivers/usb/otg/msm_otg.c
> +++ b/drivers/usb/otg/msm_otg.c
> @@ -167,6 +167,32 @@ put_3p3:
> return rc;
> }
>
> +#ifdef CONFIG_PM_SLEEP
> +static int usb_phy_susp_dig_vol = 500000;
What's the point of making this variable? It doesn't seem to be changed
anywhere...
> @@ -489,6 +516,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
> */
> writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
>
> + if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
> + motg->pdata->phy_type == OTG_PMIC_CONTROL)
This is never true, I guess. Did you mean || ISO &&?
> + writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
> +
> clk_disable(motg->pclk);
> clk_disable(motg->clk);
> if (motg->core_clk)
> @@ -497,6 +528,12 @@ static int msm_otg_suspend(struct msm_otg *motg)
> if (!IS_ERR(motg->pclk_src))
> clk_disable(motg->pclk_src);
>
> + if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
> + motg->pdata->phy_type == OTG_PMIC_CONTROL) {
This is never true either...
> + msm_hsusb_ldo_enable(0);
> + msm_hsusb_config_vddcx(0);
> + }
> +
> if (device_may_wakeup(otg->dev))
> enable_irq_wake(motg->irq);
> if (bus)
> @@ -527,6 +564,13 @@ static int msm_otg_resume(struct msm_otg *motg)
> if (motg->core_clk)
> clk_enable(motg->core_clk);
>
> + if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
> + motg->pdata->phy_type == OTG_PMIC_CONTROL) {
Neither is this one...
WBR, Sergei
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
2011-04-28 12:18 ` [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Sergei Shtylyov
@ 2011-04-29 5:16 ` Pavan Kondeti
0 siblings, 0 replies; 45+ messages in thread
From: Pavan Kondeti @ 2011-04-29 5:16 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: greg, linux-usb, linux-arm-msm, Anji jonnala
Hi Sergei
Thanks for review.
On 4/28/2011 5:48 PM, Sergei Shtylyov wrote:
> Hello.
>
> On 28-04-2011 12:01, Pavankumar Kondeti wrote:
>
>> From: Anji jonnala <anjir@codeaurora.org>
>
<snip>
>> + /*
>> + * ITC (Interrupt Threshold Control) field is to set the maximum
>> + * rate at which the device controller will issue interrupts.
>> + * The maximum interrupt interval measured in micro frames.
>> + * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
>> + * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
>> + * can be set to lesser value to gain performance.
>> + */
>> + if (udc->udc_driver->flags && CI13XXX_ZERO_ITC)
>
> I think you meant bitwise AND (&) here.
Yes. I will fix it and resend the patch.
Thanks,
Pavan
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960
2011-04-28 14:49 ` Sergei Shtylyov
@ 2011-04-29 5:20 ` Pavan Kondeti
0 siblings, 0 replies; 45+ messages in thread
From: Pavan Kondeti @ 2011-04-29 5:20 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: greg, linux-usb, linux-arm-msm
Hi Sergei
Thanks for review.
On 4/28/2011 8:19 PM, Sergei Shtylyov wrote:
> Hello.
>
> Pavankumar Kondeti wrote:
>
>> Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
> [...]
>
>> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
>> index 425418d..fe040a2 100644
>> --- a/drivers/usb/otg/msm_otg.c
>> +++ b/drivers/usb/otg/msm_otg.c
>> @@ -167,6 +167,32 @@ put_3p3:
>> return rc;
>> }
>>
>> +#ifdef CONFIG_PM_SLEEP
>> +static int usb_phy_susp_dig_vol = 500000;
>
> What's the point of making this variable? It doesn't seem to be changed
> anywhere...
>
Correct. I will change it to a macro.
>> @@ -489,6 +516,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
>> */
>> writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
>>
>> + if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
>> + motg->pdata->phy_type == OTG_PMIC_CONTROL)
>
> This is never true, I guess. Did you mean || ISO &&?
>
:-(
It should be
if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
motg->pdata->otg_control == OTG_PMIC_CONTROL)
^^^^^^^^^^^
Thanks,
Pavan
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
` (4 preceding siblings ...)
2011-04-28 12:18 ` [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Sergei Shtylyov
@ 2011-04-29 5:22 ` Pavankumar Kondeti
2011-04-29 5:22 ` [PATCH 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
` (2 more replies)
2011-05-02 6:36 ` [PATCH V2 0/5] USB Charging, PHY init and " Pavankumar Kondeti
` (3 subsequent siblings)
9 siblings, 3 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-29 5:22 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
ITC (Interrupt Threshold Control) field is to set the maximum rate at which
the device controller will issue interrupts. The maximum interrupt interval
is measured in micro frames. Valid values are 0, 1, 2, 4, 8, 16, 32, 64.
The default value is 8 micro frames. Set ITC to zero for MSM to gain
performance.
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/gadget/ci13xxx_msm.c | 3 ++-
drivers/usb/gadget/ci13xxx_udc.c | 11 +++++++++++
drivers/usb/gadget/ci13xxx_udc.h | 3 +++
3 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 139ac94..aa8319b 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -64,7 +64,8 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
- CI13XXX_DISABLE_STREAMING,
+ CI13XXX_DISABLE_STREAMING |
+ CI13XXX_ZERO_ITC,
.notify_event = ci13xxx_msm_notify_event,
};
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index e09178b..15857e0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -318,6 +318,17 @@ static int hw_device_reset(struct ci13xxx *udc)
hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
+ /*
+ * ITC (Interrupt Threshold Control) field is to set the maximum
+ * rate at which the device controller will issue interrupts.
+ * The maximum interrupt interval measured in micro frames.
+ * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
+ * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
+ * can be set to lesser value to gain performance.
+ */
+ if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
+ hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
+
if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
pr_err("cannot enter in device mode");
pr_err("lpm = %i", hw_bank.lpm);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 2370777..a230325 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -108,6 +108,7 @@ struct ci13xxx_udc_driver {
#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
#define CI13XXX_PULLUP_ON_VBUS BIT(2)
#define CI13XXX_DISABLE_STREAMING BIT(3)
+#define CI13XXX_ZERO_ITC BIT(4)
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_STOPPED_EVENT 1
@@ -189,6 +190,8 @@ struct ci13xxx {
#define USBMODE_CM_HOST (0x03UL << 0)
#define USBMODE_SLOM BIT(3)
#define USBMODE_SDIS BIT(4)
+#define USBCMD_ITC(n) (n << 16) /* n = 0, 1, 2, 4, 8, 16, 32, 64 */
+#define USBCMD_ITC_MASK (0xFF << 16)
/* ENDPTCTRL */
#define ENDPTCTRL_RXS BIT(0)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 2/5] USB: OTG: vote for dayatona fabric clock
2011-04-29 5:22 ` Pavankumar Kondeti
@ 2011-04-29 5:22 ` Pavankumar Kondeti
2011-04-29 5:22 ` [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
[not found] ` <1304054532-3523-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-29 5:22 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
HSUSB core clock is derived from daytona fabric clock and for
HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
cannot tolerate daytona fabric clock change in the middle of HSUSB
operational, vote for maximum Daytona fabric clock
while usb is operational
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 37 +++++++++++++++++++++++++++++++++++--
include/linux/usb/msm_hsusb.h | 7 +++++--
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 2965986..cfbb606 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -324,6 +324,9 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src))
+ clk_disable(motg->pclk_src);
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -347,6 +350,9 @@ static int msm_otg_resume(struct msm_otg *motg)
if (!atomic_read(&motg->in_lpm))
return 0;
+ if (!IS_ERR(motg->pclk_src))
+ clk_enable(motg->pclk_src);
+
clk_enable(motg->pclk);
clk_enable(motg->clk);
if (motg->core_clk)
@@ -862,12 +868,31 @@ static int __init msm_otg_probe(struct platform_device *pdev)
ret = PTR_ERR(motg->clk);
goto put_phy_reset_clk;
}
+ clk_set_rate(motg->clk, 60000000);
+
+ /*
+ * If USB Core is running its protocol engine based on CORE CLK,
+ * CORE CLK must be running at >55Mhz for correct HSUSB
+ * operation and USB core cannot tolerate frequency changes on
+ * CORE CLK. For such USB cores, vote for maximum clk frequency
+ * on pclk source
+ */
+ if (motg->pdata->pclk_src_name) {
+ motg->pclk_src = clk_get(&pdev->dev,
+ motg->pdata->pclk_src_name);
+ if (IS_ERR(motg->pclk_src))
+ goto put_clk;
+ clk_set_rate(motg->pclk_src, INT_MAX);
+ clk_enable(motg->pclk_src);
+ } else
+ motg->pclk_src = ERR_PTR(-ENOENT);
+
motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
if (IS_ERR(motg->pclk)) {
dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
ret = PTR_ERR(motg->pclk);
- goto put_clk;
+ goto put_pclk_src;
}
/*
@@ -954,7 +979,11 @@ free_regs:
put_core_clk:
if (motg->core_clk)
clk_put(motg->core_clk);
- clk_put(motg->pclk);
+put_pclk_src:
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
put_clk:
clk_put(motg->clk);
put_phy_reset_clk:
@@ -1004,6 +1033,10 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->clk);
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 3657403..31ef185 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -64,7 +64,8 @@ enum otg_control_type {
* @otg_control: OTG switch controlled by user/Id pin
* @default_mode: Default operational mode. Applicable only if
* OTG switch is controller by user.
- *
+ * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k
+ * dfab_usb_hs_clk in case of 8660 and 8960.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -74,6 +75,7 @@ struct msm_otg_platform_data {
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
void (*setup_gpio)(enum usb_otg_state state);
+ char *pclk_src_name;
};
/**
@@ -83,6 +85,7 @@ struct msm_otg_platform_data {
* @irq: IRQ number assigned for HSUSB controller.
* @clk: clock struct of usb_hs_clk.
* @pclk: clock struct of usb_hs_pclk.
+ * @pclk_src: pclk source for voting.
* @phy_reset_clk: clock struct of usb_phy_clk.
* @core_clk: clock struct of usb_hs_core_clk.
* @regs: ioremapped register base address.
@@ -90,7 +93,6 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
- *
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -98,6 +100,7 @@ struct msm_otg {
int irq;
struct clk *clk;
struct clk *pclk;
+ struct clk *pclk_src;
struct clk *phy_reset_clk;
struct clk *core_clk;
void __iomem *regs;
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 3/5] USB: OTG: msm: Implement charger detection
[not found] ` <1304054532-3523-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-04-29 5:22 ` Pavankumar Kondeti
2011-04-29 5:22 ` [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
1 sibling, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-29 5:22 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, Pavankumar Kondeti
Implement good battery algorithm defined in the battery charging V1.2 spec
for detecting different charging ports. USB hardware is put into low power
mode when connected to a dedicated charging port. vbus_draw and set_power
methods are implemented for determining the allowed current from Host in
different states (un-configured/suspend/configured).
The charger block is implemented using vendor specific registers and the
PHY used in MSM8960(28nm PHY) different from older targets like MSM8x60
and MSM7x30(45nm PHY). The PHY vendor and product id registers are not
implemented in the above chipsets. Hence PHY type is passed via platform
data.
Signed-off-by: Pavankumar Kondeti <pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/usb/gadget/ci13xxx_udc.c | 10 +
drivers/usb/otg/msm_otg.c | 380 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 72 +++++++-
3 files changed, 457 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 15857e0..6000714 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2508,6 +2508,15 @@ out:
return ret;
}
+static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+ struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+
+ if (udc->transceiver)
+ return otg_set_power(udc->transceiver, mA);
+ return -ENOTSUPP;
+}
+
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
@@ -2516,6 +2525,7 @@ out:
static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci13xxx_vbus_session,
.wakeup = ci13xxx_wakeup,
+ .vbus_draw = ci13xxx_vbus_draw,
};
/**
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index cfbb606..526a650 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -409,6 +409,33 @@ skip_phy_resume:
}
#endif
+static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
+{
+ if (motg->cur_power == mA)
+ return;
+
+ /* TODO: Notify PMIC about available current */
+ dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
+ motg->cur_power = mA;
+}
+
+static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+ struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+ /*
+ * Gadget driver uses set_power method to notify about the
+ * available current based on suspend/configured states.
+ *
+ * IDEV_CHG can be drawn irrespective of suspend/un-configured
+ * states when CDP/ACA is connected.
+ */
+ if (motg->chg_type == USB_SDP_CHARGER)
+ msm_otg_notify_charger(motg, mA);
+
+ return 0;
+}
+
static void msm_otg_start_host(struct otg_transceiver *otg, int on)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -563,6 +590,306 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg,
return 0;
}
+static bool msm_chg_check_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* put it in host mode for enabling D- source */
+ chg_det &= ~(1 << 2);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DM as current source, DP as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x8, 0x85);
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DP as current source, DM as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 line_state;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x15);
+ ret = !(line_state & 1);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x87);
+ ret = line_state & 2;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_disable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ chg_det &= ~(1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ ulpi_write(otg, 0x10, 0x86);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_enable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn on D+ current source */
+ chg_det |= (1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Data contact detection enable */
+ ulpi_write(otg, 0x10, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_on(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ /* put the controller in non-driving mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ udelay(100);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_off(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ break;
+ default:
+ break;
+ }
+
+ /* put the controller in normal mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+}
+
+#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
+#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
+static void msm_chg_detect_work(struct work_struct *w)
+{
+ struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
+ struct otg_transceiver *otg = &motg->otg;
+ bool is_dcd, tmout, vout;
+ unsigned long delay;
+
+ dev_dbg(otg->dev, "chg detection work\n");
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ pm_runtime_get_sync(otg->dev);
+ msm_chg_block_on(motg);
+ msm_chg_enable_dcd(motg);
+ motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
+ motg->dcd_retries = 0;
+ delay = MSM_CHG_DCD_POLL_TIME;
+ break;
+ case USB_CHG_STATE_WAIT_FOR_DCD:
+ is_dcd = msm_chg_check_dcd(motg);
+ tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
+ if (is_dcd || tmout) {
+ msm_chg_disable_dcd(motg);
+ msm_chg_enable_primary_det(motg);
+ delay = MSM_CHG_PRIMARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_DCD_DONE;
+ } else {
+ delay = MSM_CHG_DCD_POLL_TIME;
+ }
+ break;
+ case USB_CHG_STATE_DCD_DONE:
+ vout = msm_chg_check_primary_det(motg);
+ if (vout) {
+ msm_chg_enable_secondary_det(motg);
+ delay = MSM_CHG_SECONDARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
+ } else {
+ motg->chg_type = USB_SDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ delay = 0;
+ }
+ break;
+ case USB_CHG_STATE_PRIMARY_DONE:
+ vout = msm_chg_check_secondary_det(motg);
+ if (vout)
+ motg->chg_type = USB_DCP_CHARGER;
+ else
+ motg->chg_type = USB_CDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
+ /* fall through */
+ case USB_CHG_STATE_SECONDARY_DONE:
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ case USB_CHG_STATE_DETECTED:
+ msm_chg_block_off(motg);
+ dev_dbg(otg->dev, "charger = %d\n", motg->chg_type);
+ schedule_work(&motg->sm_work);
+ return;
+ default:
+ return;
+ }
+
+ schedule_delayed_work(&motg->chg_work, delay);
+}
+
/*
* We support OTG, Peripheral only and Host only configurations. In case
* of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
@@ -633,9 +960,48 @@ static void msm_otg_sm_work(struct work_struct *w)
writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
msm_otg_start_host(otg, 1);
otg->state = OTG_STATE_A_HOST;
- } else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) {
- msm_otg_start_peripheral(otg, 1);
- otg->state = OTG_STATE_B_PERIPHERAL;
+ } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ msm_chg_detect_work(&motg->chg_work.work);
+ break;
+ case USB_CHG_STATE_DETECTED:
+ switch (motg->chg_type) {
+ case USB_DCP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ break;
+ case USB_CDP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ case USB_SDP_CHARGER:
+ msm_otg_notify_charger(motg, IUNIT);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ /*
+ * If charger detection work is pending, decrement
+ * the pm usage counter to balance with the one that
+ * is incremented in charger detection work.
+ */
+ if (cancel_delayed_work_sync(&motg->chg_work)) {
+ pm_runtime_put_sync(otg->dev);
+ msm_otg_reset(otg);
+ }
+ msm_otg_notify_charger(motg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
}
pm_runtime_put_sync(otg->dev);
break;
@@ -643,7 +1009,10 @@ static void msm_otg_sm_work(struct work_struct *w)
dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
if (!test_bit(B_SESS_VLD, &motg->inputs) ||
!test_bit(ID, &motg->inputs)) {
+ msm_otg_notify_charger(motg, 0);
msm_otg_start_peripheral(otg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
otg->state = OTG_STATE_B_IDLE;
msm_otg_reset(otg);
schedule_work(w);
@@ -935,6 +1304,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
writel(0, USB_OTGSC);
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+ INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
"msm_otg", motg);
if (ret) {
@@ -945,6 +1315,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
otg->init = msm_otg_reset;
otg->set_host = msm_otg_set_host;
otg->set_peripheral = msm_otg_set_peripheral;
+ otg->set_power = msm_otg_set_power;
otg->io_ops = &msm_otg_io_ops;
@@ -1003,6 +1374,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
return -EBUSY;
msm_otg_debugfs_cleanup();
+ cancel_delayed_work_sync(&motg->chg_work);
cancel_work_sync(&motg->sm_work);
pm_runtime_resume(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 31ef185..00311fe 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -54,6 +54,64 @@ enum otg_control_type {
};
/**
+ * PHY used in
+ *
+ * INVALID_PHY Unsupported PHY
+ * CI_45NM_INTEGRATED_PHY Chipidea 45nm integrated PHY
+ * SNPS_28NM_INTEGRATED_PHY Synopsis 28nm integrated PHY
+ *
+ */
+enum msm_usb_phy_type {
+ INVALID_PHY = 0,
+ CI_45NM_INTEGRATED_PHY,
+ SNPS_28NM_INTEGRATED_PHY,
+};
+
+#define IDEV_CHG_MAX 1500
+#define IUNIT 100
+
+/**
+ * Different states involved in USB charger detection.
+ *
+ * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
+ * process is not yet started.
+ * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
+ * USB_CHG_STATE_DCD_DONE Data pin contact is detected.
+ * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
+ * between SDP and DCP/CDP).
+ * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
+ * between DCP and CDP).
+ * USB_CHG_STATE_DETECTED USB charger type is determined.
+ *
+ */
+enum usb_chg_state {
+ USB_CHG_STATE_UNDEFINED = 0,
+ USB_CHG_STATE_WAIT_FOR_DCD,
+ USB_CHG_STATE_DCD_DONE,
+ USB_CHG_STATE_PRIMARY_DONE,
+ USB_CHG_STATE_SECONDARY_DONE,
+ USB_CHG_STATE_DETECTED,
+};
+
+/**
+ * USB charger types
+ *
+ * USB_INVALID_CHARGER Invalid USB charger.
+ * USB_SDP_CHARGER Standard downstream port. Refers to a downstream port
+ * on USB2.0 compliant host/hub.
+ * USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
+ * USB_CDP_CHARGER Charging downstream port. Enumeration can happen and
+ * IDEV_CHG_MAX can be drawn irrespective of USB state.
+ *
+ */
+enum usb_chg_type {
+ USB_INVALID_CHARGER = 0,
+ USB_SDP_CHARGER,
+ USB_DCP_CHARGER,
+ USB_CDP_CHARGER,
+};
+
+/**
* struct msm_otg_platform_data - platform device data
* for msm_otg driver.
* @phy_init_seq: PHY configuration sequence. val, reg pairs
@@ -74,6 +132,7 @@ struct msm_otg_platform_data {
enum usb_mode_type mode;
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
+ enum msm_usb_phy_type phy_type;
void (*setup_gpio)(enum usb_otg_state state);
char *pclk_src_name;
};
@@ -93,6 +152,12 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
+ * @cur_power: The amount of mA available from downstream port.
+ * @chg_work: Charger detection work.
+ * @chg_state: The state of charger detection process.
+ * @chg_type: The type of charger attached.
+ * @dcd_retires: The retry count used to track Data contact
+ * detection process.
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -110,6 +175,11 @@ struct msm_otg {
struct work_struct sm_work;
atomic_t in_lpm;
int async_int;
+ unsigned cur_power;
+ struct delayed_work chg_work;
+ enum usb_chg_state chg_state;
+ enum usb_chg_type chg_type;
+ u8 dcd_retries;
};
#endif
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains
2011-04-29 5:22 ` Pavankumar Kondeti
2011-04-29 5:22 ` [PATCH 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
@ 2011-04-29 5:22 ` Pavankumar Kondeti
[not found] ` <1304054532-3523-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-29 5:22 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 194 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 193 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 526a650..425418d 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -38,6 +38,7 @@
#include <linux/usb/hcd.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
@@ -45,6 +46,175 @@
#define DRIVER_NAME "msm_otg"
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
+
+#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
+#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
+#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
+#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
+#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
+#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
+#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+
+static struct regulator *hsusb_3p3;
+static struct regulator *hsusb_1p8;
+static struct regulator *hsusb_vddcx;
+
+static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
+{
+ int ret = 0;
+
+ if (init) {
+ hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+ if (IS_ERR(hsusb_vddcx)) {
+ dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+ return PTR_ERR(hsusb_vddcx);
+ }
+
+ ret = regulator_set_voltage(hsusb_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage"
+ "for hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ return ret;
+ }
+
+ ret = regulator_enable(hsusb_vddcx);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ }
+ } else {
+ ret = regulator_set_voltage(hsusb_vddcx, 0,
+ USB_PHY_VDD_DIG_VOL_MIN);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage"
+ "for hsusb vddcx\n");
+ return ret;
+ }
+ ret = regulator_disable(hsusb_vddcx);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
+ return ret;
+ }
+
+ regulator_put(hsusb_vddcx);
+ }
+
+ return ret;
+}
+
+static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
+{
+ int rc = 0;
+
+ if (init) {
+ hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
+ if (IS_ERR(hsusb_3p3)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
+ return PTR_ERR(hsusb_3p3);
+ }
+
+ rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
+ USB_PHY_3P3_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level for"
+ "hsusb 3p3\n");
+ goto put_3p3;
+ }
+ rc = regulator_enable(hsusb_3p3);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
+ goto put_3p3_lpm;
+ }
+ hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
+ if (IS_ERR(hsusb_1p8)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
+ rc = PTR_ERR(hsusb_1p8);
+ goto put_3p3_lpm;
+ }
+ rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
+ USB_PHY_1P8_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level for"
+ "hsusb 1p8\n");
+ goto put_1p8;
+ }
+ rc = regulator_enable(hsusb_1p8);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
+ goto disable_1p8;
+ }
+
+ return 0;
+ }
+
+disable_1p8:
+ regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
+ regulator_disable(hsusb_1p8);
+put_1p8:
+ regulator_put(hsusb_1p8);
+put_3p3_lpm:
+ regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
+put_3p3:
+ regulator_put(hsusb_3p3);
+ return rc;
+}
+
+static int msm_hsusb_ldo_set_mode(int on)
+{
+ int ret = 0;
+
+ if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
+ pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
+ pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (on) {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator:"
+ "HSUSB_1p8\n", __func__);
+ return ret;
+ }
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator:"
+ "HSUSB_3p3\n", __func__);
+ regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ return ret;
+ }
+ } else {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator:"
+ "HSUSB_1p8\n", __func__);
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator:"
+ "HSUSB_3p3\n", __func__);
+ }
+
+ pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+ return ret < 0 ? ret : 0;
+}
+
static int ulpi_read(struct otg_transceiver *otg, u32 reg)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -353,7 +523,6 @@ static int msm_otg_resume(struct msm_otg *motg)
if (!IS_ERR(motg->pclk_src))
clk_enable(motg->pclk_src);
- clk_enable(motg->pclk);
clk_enable(motg->clk);
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -1297,6 +1466,24 @@ static int __init msm_otg_probe(struct platform_device *pdev)
clk_enable(motg->clk);
clk_enable(motg->pclk);
+
+ ret = msm_hsusb_init_vddcx(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+ goto free_regs;
+ }
+
+ ret = msm_hsusb_ldo_init(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+ goto free_config_vddcx;
+ }
+ ret = msm_hsusb_ldo_set_mode(1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+ goto free_ldo_init;
+ }
+
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -1345,6 +1532,10 @@ free_irq:
disable_clks:
clk_disable(motg->pclk);
clk_disable(motg->clk);
+free_ldo_init:
+ msm_hsusb_ldo_init(motg, 0);
+free_config_vddcx:
+ msm_hsusb_init_vddcx(motg, 0);
free_regs:
iounmap(motg->regs);
put_core_clk:
@@ -1409,6 +1600,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->pclk_src);
clk_put(motg->pclk_src);
}
+ msm_hsusb_ldo_init(motg, 0);
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960
[not found] ` <1304054532-3523-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-04-29 5:22 ` [PATCH 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
@ 2011-04-29 5:22 ` Pavankumar Kondeti
1 sibling, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-04-29 5:22 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, Pavankumar Kondeti
Signed-off-by: Pavankumar Kondeti <pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/usb/otg/msm_otg.c | 64 ++++++++++++++++++++++++++++++++------
include/linux/usb/msm_hsusb_hw.h | 2 +
2 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 425418d..76f97fd 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -167,6 +167,32 @@ put_3p3:
return rc;
}
+#ifdef CONFIG_PM_SLEEP
+#define USB_PHY_SUSP_DIG_VOL 500000
+static int msm_hsusb_config_vddcx(int high)
+{
+ int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+ int min_vol;
+ int ret;
+
+ if (high)
+ min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+ else
+ min_vol = USB_PHY_SUSP_DIG_VOL;
+
+ ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+ if (ret) {
+ pr_err("%s: unable to set the voltage for regulator"
+ "HSUSB_VDDCX\n", __func__);
+ return ret;
+ }
+
+ pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+ return ret;
+}
+#endif
+
static int msm_hsusb_ldo_set_mode(int on)
{
int ret = 0;
@@ -438,27 +464,28 @@ static int msm_otg_suspend(struct msm_otg *motg)
disable_irq(motg->irq);
/*
+ * Chipidea 45-nm PHY suspend sequence:
+ *
* Interrupt Latch Register auto-clear feature is not present
* in all PHY versions. Latch register is clear on read type.
* Clear latch register to avoid spurious wakeup from
* low power mode (LPM).
- */
- ulpi_read(otg, 0x14);
-
- /*
+ *
* PHY comparators are disabled when PHY enters into low power
* mode (LPM). Keep PHY comparators ON in LPM only when we expect
* VBUS/Id notifications from USB PHY. Otherwise turn off USB
* PHY comparators. This save significant amount of power.
- */
- if (pdata->otg_control == OTG_PHY_CONTROL)
- ulpi_write(otg, 0x01, 0x30);
-
- /*
+ *
* PLL is not turned off when PHY enters into low power mode (LPM).
* Disable PLL for maximum power savings.
*/
- ulpi_write(otg, 0x08, 0x09);
+
+ if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
+ ulpi_read(otg, 0x14);
+ if (pdata->otg_control == OTG_PHY_CONTROL)
+ ulpi_write(otg, 0x01, 0x30);
+ ulpi_write(otg, 0x08, 0x09);
+ }
/*
* PHY may take some time or even fail to enter into low power
@@ -489,6 +516,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
*/
writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL)
+ writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
+
clk_disable(motg->pclk);
clk_disable(motg->clk);
if (motg->core_clk)
@@ -497,6 +528,12 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (!IS_ERR(motg->pclk_src))
clk_disable(motg->pclk_src);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_enable(0);
+ msm_hsusb_config_vddcx(0);
+ }
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -527,6 +564,13 @@ static int msm_otg_resume(struct msm_otg *motg)
if (motg->core_clk)
clk_enable(motg->core_clk);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_enable(1);
+ msm_hsusb_config_vddcx(1);
+ writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
+ }
+
temp = readl(USB_USBCMD);
temp &= ~ASYNC_INTR_CTRL;
temp &= ~ULPI_STP_CTRL;
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 7d1babb..6e97a2d 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
#define USB_PORTSC (MSM_USB_BASE + 0x0184)
#define USB_OTGSC (MSM_USB_BASE + 0x01A4)
#define USB_USBMODE (MSM_USB_BASE + 0x01A8)
+#define USB_PHY_CTRL (MSM_USB_BASE + 0x0240)
#define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148)
@@ -42,6 +43,7 @@
#define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */
#define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */
+#define PHY_RETEN (1 << 1) /* PHY retention enable/disable */
/* OTG definitions */
#define OTGSC_INTSTS_MASK (0x7f << 16)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains
2011-04-28 8:01 ` [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
@ 2011-04-29 10:14 ` Sergei Shtylyov
2011-05-02 6:03 ` Pavan Kondeti
0 siblings, 1 reply; 45+ messages in thread
From: Sergei Shtylyov @ 2011-04-29 10:14 UTC (permalink / raw)
To: Pavankumar Kondeti; +Cc: greg, linux-usb, linux-arm-msm, Anji jonnala
On 28.04.2011 12:01, Pavankumar Kondeti wrote:
> From: Anji jonnala <anjir@codeaurora.org>
> Signed-off-by: Anji jonnala <anjir@codeaurora.org>
> Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
[...]
> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
> index 526a650..425418d 100644
> --- a/drivers/usb/otg/msm_otg.c
> +++ b/drivers/usb/otg/msm_otg.c
> @@ -38,6 +38,7 @@
> #include<linux/usb/hcd.h>
> #include<linux/usb/msm_hsusb.h>
> #include<linux/usb/msm_hsusb_hw.h>
> +#include<linux/regulator/consumer.h>
>
> #include<mach/clk.h>
>
> @@ -45,6 +46,175 @@
> #define DRIVER_NAME "msm_otg"
>
> #define ULPI_IO_TIMEOUT_USEC (10 * 1000)
> +
> +#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
> +#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
> +#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
> +#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
> +
> +#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
> +#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
> +#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
> +#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
> +
> +#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
> +#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
> +
> +static struct regulator *hsusb_3p3;
> +static struct regulator *hsusb_1p8;
> +static struct regulator *hsusb_vddcx;
> +
> +static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
> +{
> + int ret = 0;
> +
> + if (init) {
> + hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
> + if (IS_ERR(hsusb_vddcx)) {
> + dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
> + return PTR_ERR(hsusb_vddcx);
> + }
> +
> + ret = regulator_set_voltage(hsusb_vddcx,
> + USB_PHY_VDD_DIG_VOL_MIN,
> + USB_PHY_VDD_DIG_VOL_MAX);
> + if (ret) {
> + dev_err(motg->otg.dev, "unable to set the voltage"
> + "for hsusb vddcx\n");
> + regulator_put(hsusb_vddcx);
> + return ret;
> + }
> +
> + ret = regulator_enable(hsusb_vddcx);
> + if (ret) {
> + dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
> + regulator_put(hsusb_vddcx);
> + }
> + } else {
> + ret = regulator_set_voltage(hsusb_vddcx, 0,
> + USB_PHY_VDD_DIG_VOL_MIN);
> + if (ret) {
> + dev_err(motg->otg.dev, "unable to set the voltage"
> + "for hsusb vddcx\n");
> + return ret;
> + }
> + ret = regulator_disable(hsusb_vddcx);
> + if (ret) {
> + dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
> + return ret;
I suspect you should call regulator_put() on error cases as well...
> + }
> +
> + regulator_put(hsusb_vddcx);
> + }
> +
> + return ret;
> +}
> +
> +static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
> +{
> + int rc = 0;
> +
> + if (init) {
> + hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
> + if (IS_ERR(hsusb_3p3)) {
> + dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
> + return PTR_ERR(hsusb_3p3);
> + }
> +
> + rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
> + USB_PHY_3P3_VOL_MAX);
> + if (rc) {
> + dev_err(motg->otg.dev, "unable to set voltage level for"
> + "hsusb 3p3\n");
> + goto put_3p3;
> + }
> + rc = regulator_enable(hsusb_3p3);
> + if (rc) {
> + dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
> + goto put_3p3_lpm;
> + }
> + hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
> + if (IS_ERR(hsusb_1p8)) {
> + dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
> + rc = PTR_ERR(hsusb_1p8);
> + goto put_3p3_lpm;
> + }
> + rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
> + USB_PHY_1P8_VOL_MAX);
> + if (rc) {
> + dev_err(motg->otg.dev, "unable to set voltage level for"
> + "hsusb 1p8\n");
> + goto put_1p8;
> + }
> + rc = regulator_enable(hsusb_1p8);
> + if (rc) {
> + dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
> + goto disable_1p8;
> + }
> +
> + return 0;
> + }
> +
> +disable_1p8:
> + regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
> + regulator_disable(hsusb_1p8);
Why call regualator_disable() if regulator_enable() has just failed?
> +put_1p8:
> + regulator_put(hsusb_1p8);
> +put_3p3_lpm:
> + regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
> +put_3p3:
> + regulator_put(hsusb_3p3);
> + return rc;
> +}
[...]
> @@ -1345,6 +1532,10 @@ free_irq:
> disable_clks:
> clk_disable(motg->pclk);
> clk_disable(motg->clk);
> +free_ldo_init:
'ldo_exit' perhaps?
> + msm_hsusb_ldo_init(motg, 0);
> +free_config_vddcx:
'vddcx_exit' perhaps?
> + msm_hsusb_init_vddcx(motg, 0);
> free_regs:
> iounmap(motg->regs);
> put_core_clk:
WBR, Sergei
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains
2011-04-29 10:14 ` Sergei Shtylyov
@ 2011-05-02 6:03 ` Pavan Kondeti
0 siblings, 0 replies; 45+ messages in thread
From: Pavan Kondeti @ 2011-05-02 6:03 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: greg, linux-usb, linux-arm-msm, Anji jonnala
Hi Sergei,
Thanks for the review.
On 4/29/2011 3:44 PM, Sergei Shtylyov wrote:
> On 28.04.2011 12:01, Pavankumar Kondeti wrote:
>
>> From: Anji jonnala <anjir@codeaurora.org>
>
>> Signed-off-by: Anji jonnala <anjir@codeaurora.org>
>> Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
> [...]
>
<snip>
>> +static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
>> +{
>> + int ret = 0;
>> +
>> + if (init) {
>> + hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
>> + if (IS_ERR(hsusb_vddcx)) {
>> + dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
>> + return PTR_ERR(hsusb_vddcx);
>> + }
>> +
>> + ret = regulator_set_voltage(hsusb_vddcx,
>> + USB_PHY_VDD_DIG_VOL_MIN,
>> + USB_PHY_VDD_DIG_VOL_MAX);
>> + if (ret) {
>> + dev_err(motg->otg.dev, "unable to set the voltage"
>> + "for hsusb vddcx\n");
>> + regulator_put(hsusb_vddcx);
>> + return ret;
>> + }
>> +
>> + ret = regulator_enable(hsusb_vddcx);
>> + if (ret) {
>> + dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
>> + regulator_put(hsusb_vddcx);
>> + }
>> + } else {
>> + ret = regulator_set_voltage(hsusb_vddcx, 0,
>> + USB_PHY_VDD_DIG_VOL_MIN);
>> + if (ret) {
>> + dev_err(motg->otg.dev, "unable to set the voltage"
>> + "for hsusb vddcx\n");
>> + return ret;
>> + }
>> + ret = regulator_disable(hsusb_vddcx);
>> + if (ret) {
>> + dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
>> + return ret;
>
> I suspect you should call regulator_put() on error cases as well...
>
Yep. Will fix it next patch set.
>> + }
>> +
>> + regulator_put(hsusb_vddcx);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
>> +{
>> + int rc = 0;
>> +
>> + if (init) {
>> + hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
>> + if (IS_ERR(hsusb_3p3)) {
>> + dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
>> + return PTR_ERR(hsusb_3p3);
>> + }
>> +
>> + rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
>> + USB_PHY_3P3_VOL_MAX);
>> + if (rc) {
>> + dev_err(motg->otg.dev, "unable to set voltage level for"
>> + "hsusb 3p3\n");
>> + goto put_3p3;
>> + }
>> + rc = regulator_enable(hsusb_3p3);
>> + if (rc) {
>> + dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
>> + goto put_3p3_lpm;
>> + }
>> + hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
>> + if (IS_ERR(hsusb_1p8)) {
>> + dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
>> + rc = PTR_ERR(hsusb_1p8);
>> + goto put_3p3_lpm;
>> + }
>> + rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
>> + USB_PHY_1P8_VOL_MAX);
>> + if (rc) {
>> + dev_err(motg->otg.dev, "unable to set voltage level for"
>> + "hsusb 1p8\n");
>> + goto put_1p8;
>> + }
>> + rc = regulator_enable(hsusb_1p8);
>> + if (rc) {
>> + dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
>> + goto disable_1p8;
>> + }
>> +
>> + return 0;
>> + }
>> +
>> +disable_1p8:
>> + regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
>> + regulator_disable(hsusb_1p8);
>
> Why call regualator_disable() if regulator_enable() has just failed?
Correct. regulator_disable() call is not required.
The error handling here seems to be wrong. We don't need to explicitly
call regulator_set_voltage() upon regulator_enable() failure. will fix
this in next patch set.
>
>> +put_1p8:
>> + regulator_put(hsusb_1p8);
>> +put_3p3_lpm:
>> + regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
>> +put_3p3:
>> + regulator_put(hsusb_3p3);
>> + return rc;
>> +}
> [...]
>> @@ -1345,6 +1532,10 @@ free_irq:
>> disable_clks:
>> clk_disable(motg->pclk);
>> clk_disable(motg->clk);
>> +free_ldo_init:
>
> 'ldo_exit' perhaps?
>
sounds good.
>> + msm_hsusb_ldo_init(motg, 0);
>> +free_config_vddcx:
>
> 'vddcx_exit' perhaps?
>
sounds good.
>> + msm_hsusb_init_vddcx(motg, 0);
>> free_regs:
>> iounmap(motg->regs);
>> put_core_clk:
>
> WBR, Sergei
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH V2 0/5] USB Charging, PHY init and suspend support for MSM8960
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
` (5 preceding siblings ...)
2011-04-29 5:22 ` Pavankumar Kondeti
@ 2011-05-02 6:36 ` Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
` (4 more replies)
[not found] ` <1303977693-18389-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
` (2 subsequent siblings)
9 siblings, 5 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 6:36 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, davidb, sshtylyov, Pavankumar Kondeti
This patch series adds PHY based charging detection, PHY initialization and
suspend support for MSM8960 target.
Changelog
- V2
- logical AND operator is used instead of bitwiese AND for testing flags.
- Fixed error path and label names as per Sergei's comments.
- Fixed a typo mistake (s/phy_type/otg_control) pointed out by Sergei.
- Changed a never-changed-variable into a macro.
Anji jonnala (3):
USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
USB: OTG: vote for dayatona fabric clock
USB: OTG: msm: Configure PHY Analog and Digital voltage domains
Pavankumar Kondeti (2):
USB: OTG: msm: Implement charger detection
USB: OTG: msm: Add PHY suspend support for MSM8960
drivers/usb/gadget/ci13xxx_msm.c | 3 +-
drivers/usb/gadget/ci13xxx_udc.c | 21 ++
drivers/usb/gadget/ci13xxx_udc.h | 3 +
drivers/usb/otg/msm_otg.c | 671 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 79 +++++-
include/linux/usb/msm_hsusb_hw.h | 2 +
6 files changed, 758 insertions(+), 21 deletions(-)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH V2 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
2011-05-02 6:36 ` [PATCH V2 0/5] USB Charging, PHY init and " Pavankumar Kondeti
@ 2011-05-02 6:36 ` Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
` (3 subsequent siblings)
4 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 6:36 UTC (permalink / raw)
To: greg, linux-usb
Cc: linux-arm-msm, davidb, sshtylyov, Anji jonnala,
Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
ITC (Interrupt Threshold Control) field is to set the maximum rate at which
the device controller will issue interrupts. The maximum interrupt interval
is measured in micro frames. Valid values are 0, 1, 2, 4, 8, 16, 32, 64.
The default value is 8 micro frames. Set ITC to zero for MSM to gain
performance.
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/gadget/ci13xxx_msm.c | 3 ++-
drivers/usb/gadget/ci13xxx_udc.c | 11 +++++++++++
drivers/usb/gadget/ci13xxx_udc.h | 3 +++
3 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 139ac94..aa8319b 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -64,7 +64,8 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
- CI13XXX_DISABLE_STREAMING,
+ CI13XXX_DISABLE_STREAMING |
+ CI13XXX_ZERO_ITC,
.notify_event = ci13xxx_msm_notify_event,
};
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index e09178b..15857e0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -318,6 +318,17 @@ static int hw_device_reset(struct ci13xxx *udc)
hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
+ /*
+ * ITC (Interrupt Threshold Control) field is to set the maximum
+ * rate at which the device controller will issue interrupts.
+ * The maximum interrupt interval measured in micro frames.
+ * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
+ * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
+ * can be set to lesser value to gain performance.
+ */
+ if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
+ hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
+
if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
pr_err("cannot enter in device mode");
pr_err("lpm = %i", hw_bank.lpm);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 2370777..a230325 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -108,6 +108,7 @@ struct ci13xxx_udc_driver {
#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
#define CI13XXX_PULLUP_ON_VBUS BIT(2)
#define CI13XXX_DISABLE_STREAMING BIT(3)
+#define CI13XXX_ZERO_ITC BIT(4)
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_STOPPED_EVENT 1
@@ -189,6 +190,8 @@ struct ci13xxx {
#define USBMODE_CM_HOST (0x03UL << 0)
#define USBMODE_SLOM BIT(3)
#define USBMODE_SDIS BIT(4)
+#define USBCMD_ITC(n) (n << 16) /* n = 0, 1, 2, 4, 8, 16, 32, 64 */
+#define USBCMD_ITC_MASK (0xFF << 16)
/* ENDPTCTRL */
#define ENDPTCTRL_RXS BIT(0)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V2 2/5] USB: OTG: vote for dayatona fabric clock
2011-05-02 6:36 ` [PATCH V2 0/5] USB Charging, PHY init and " Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
@ 2011-05-02 6:36 ` Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
` (2 subsequent siblings)
4 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 6:36 UTC (permalink / raw)
To: greg, linux-usb
Cc: linux-arm-msm, davidb, sshtylyov, Anji jonnala,
Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
HSUSB core clock is derived from daytona fabric clock and for
HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
cannot tolerate daytona fabric clock change in the middle of HSUSB
operational, vote for maximum Daytona fabric clock
while usb is operational
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 37 +++++++++++++++++++++++++++++++++++--
include/linux/usb/msm_hsusb.h | 7 +++++--
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 2965986..cfbb606 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -324,6 +324,9 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src))
+ clk_disable(motg->pclk_src);
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -347,6 +350,9 @@ static int msm_otg_resume(struct msm_otg *motg)
if (!atomic_read(&motg->in_lpm))
return 0;
+ if (!IS_ERR(motg->pclk_src))
+ clk_enable(motg->pclk_src);
+
clk_enable(motg->pclk);
clk_enable(motg->clk);
if (motg->core_clk)
@@ -862,12 +868,31 @@ static int __init msm_otg_probe(struct platform_device *pdev)
ret = PTR_ERR(motg->clk);
goto put_phy_reset_clk;
}
+ clk_set_rate(motg->clk, 60000000);
+
+ /*
+ * If USB Core is running its protocol engine based on CORE CLK,
+ * CORE CLK must be running at >55Mhz for correct HSUSB
+ * operation and USB core cannot tolerate frequency changes on
+ * CORE CLK. For such USB cores, vote for maximum clk frequency
+ * on pclk source
+ */
+ if (motg->pdata->pclk_src_name) {
+ motg->pclk_src = clk_get(&pdev->dev,
+ motg->pdata->pclk_src_name);
+ if (IS_ERR(motg->pclk_src))
+ goto put_clk;
+ clk_set_rate(motg->pclk_src, INT_MAX);
+ clk_enable(motg->pclk_src);
+ } else
+ motg->pclk_src = ERR_PTR(-ENOENT);
+
motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
if (IS_ERR(motg->pclk)) {
dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
ret = PTR_ERR(motg->pclk);
- goto put_clk;
+ goto put_pclk_src;
}
/*
@@ -954,7 +979,11 @@ free_regs:
put_core_clk:
if (motg->core_clk)
clk_put(motg->core_clk);
- clk_put(motg->pclk);
+put_pclk_src:
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
put_clk:
clk_put(motg->clk);
put_phy_reset_clk:
@@ -1004,6 +1033,10 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->clk);
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 3657403..31ef185 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -64,7 +64,8 @@ enum otg_control_type {
* @otg_control: OTG switch controlled by user/Id pin
* @default_mode: Default operational mode. Applicable only if
* OTG switch is controller by user.
- *
+ * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k
+ * dfab_usb_hs_clk in case of 8660 and 8960.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -74,6 +75,7 @@ struct msm_otg_platform_data {
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
void (*setup_gpio)(enum usb_otg_state state);
+ char *pclk_src_name;
};
/**
@@ -83,6 +85,7 @@ struct msm_otg_platform_data {
* @irq: IRQ number assigned for HSUSB controller.
* @clk: clock struct of usb_hs_clk.
* @pclk: clock struct of usb_hs_pclk.
+ * @pclk_src: pclk source for voting.
* @phy_reset_clk: clock struct of usb_phy_clk.
* @core_clk: clock struct of usb_hs_core_clk.
* @regs: ioremapped register base address.
@@ -90,7 +93,6 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
- *
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -98,6 +100,7 @@ struct msm_otg {
int irq;
struct clk *clk;
struct clk *pclk;
+ struct clk *pclk_src;
struct clk *phy_reset_clk;
struct clk *core_clk;
void __iomem *regs;
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V2 3/5] USB: OTG: msm: Implement charger detection
2011-05-02 6:36 ` [PATCH V2 0/5] USB Charging, PHY init and " Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
@ 2011-05-02 6:36 ` Pavankumar Kondeti
[not found] ` <1304318192-24374-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-02 6:36 ` [PATCH V2 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
4 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 6:36 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, davidb, sshtylyov, Pavankumar Kondeti
Implement good battery algorithm defined in the battery charging V1.2 spec
for detecting different charging ports. USB hardware is put into low power
mode when connected to a dedicated charging port. vbus_draw and set_power
methods are implemented for determining the allowed current from Host in
different states (un-configured/suspend/configured).
The charger block is implemented using vendor specific registers and the
PHY used in MSM8960(28nm PHY) different from older targets like MSM8x60
and MSM7x30(45nm PHY). The PHY vendor and product id registers are not
implemented in the above chipsets. Hence PHY type is passed via platform
data.
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/gadget/ci13xxx_udc.c | 10 +
drivers/usb/otg/msm_otg.c | 380 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 72 +++++++-
3 files changed, 457 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 15857e0..6000714 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2508,6 +2508,15 @@ out:
return ret;
}
+static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+ struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+
+ if (udc->transceiver)
+ return otg_set_power(udc->transceiver, mA);
+ return -ENOTSUPP;
+}
+
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
@@ -2516,6 +2525,7 @@ out:
static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci13xxx_vbus_session,
.wakeup = ci13xxx_wakeup,
+ .vbus_draw = ci13xxx_vbus_draw,
};
/**
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index cfbb606..526a650 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -409,6 +409,33 @@ skip_phy_resume:
}
#endif
+static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
+{
+ if (motg->cur_power == mA)
+ return;
+
+ /* TODO: Notify PMIC about available current */
+ dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
+ motg->cur_power = mA;
+}
+
+static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+ struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+ /*
+ * Gadget driver uses set_power method to notify about the
+ * available current based on suspend/configured states.
+ *
+ * IDEV_CHG can be drawn irrespective of suspend/un-configured
+ * states when CDP/ACA is connected.
+ */
+ if (motg->chg_type == USB_SDP_CHARGER)
+ msm_otg_notify_charger(motg, mA);
+
+ return 0;
+}
+
static void msm_otg_start_host(struct otg_transceiver *otg, int on)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -563,6 +590,306 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg,
return 0;
}
+static bool msm_chg_check_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* put it in host mode for enabling D- source */
+ chg_det &= ~(1 << 2);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DM as current source, DP as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x8, 0x85);
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DP as current source, DM as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 line_state;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x15);
+ ret = !(line_state & 1);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x87);
+ ret = line_state & 2;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_disable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ chg_det &= ~(1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ ulpi_write(otg, 0x10, 0x86);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_enable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn on D+ current source */
+ chg_det |= (1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Data contact detection enable */
+ ulpi_write(otg, 0x10, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_on(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ /* put the controller in non-driving mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ udelay(100);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_off(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ break;
+ default:
+ break;
+ }
+
+ /* put the controller in normal mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+}
+
+#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
+#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
+static void msm_chg_detect_work(struct work_struct *w)
+{
+ struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
+ struct otg_transceiver *otg = &motg->otg;
+ bool is_dcd, tmout, vout;
+ unsigned long delay;
+
+ dev_dbg(otg->dev, "chg detection work\n");
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ pm_runtime_get_sync(otg->dev);
+ msm_chg_block_on(motg);
+ msm_chg_enable_dcd(motg);
+ motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
+ motg->dcd_retries = 0;
+ delay = MSM_CHG_DCD_POLL_TIME;
+ break;
+ case USB_CHG_STATE_WAIT_FOR_DCD:
+ is_dcd = msm_chg_check_dcd(motg);
+ tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
+ if (is_dcd || tmout) {
+ msm_chg_disable_dcd(motg);
+ msm_chg_enable_primary_det(motg);
+ delay = MSM_CHG_PRIMARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_DCD_DONE;
+ } else {
+ delay = MSM_CHG_DCD_POLL_TIME;
+ }
+ break;
+ case USB_CHG_STATE_DCD_DONE:
+ vout = msm_chg_check_primary_det(motg);
+ if (vout) {
+ msm_chg_enable_secondary_det(motg);
+ delay = MSM_CHG_SECONDARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
+ } else {
+ motg->chg_type = USB_SDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ delay = 0;
+ }
+ break;
+ case USB_CHG_STATE_PRIMARY_DONE:
+ vout = msm_chg_check_secondary_det(motg);
+ if (vout)
+ motg->chg_type = USB_DCP_CHARGER;
+ else
+ motg->chg_type = USB_CDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
+ /* fall through */
+ case USB_CHG_STATE_SECONDARY_DONE:
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ case USB_CHG_STATE_DETECTED:
+ msm_chg_block_off(motg);
+ dev_dbg(otg->dev, "charger = %d\n", motg->chg_type);
+ schedule_work(&motg->sm_work);
+ return;
+ default:
+ return;
+ }
+
+ schedule_delayed_work(&motg->chg_work, delay);
+}
+
/*
* We support OTG, Peripheral only and Host only configurations. In case
* of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
@@ -633,9 +960,48 @@ static void msm_otg_sm_work(struct work_struct *w)
writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
msm_otg_start_host(otg, 1);
otg->state = OTG_STATE_A_HOST;
- } else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) {
- msm_otg_start_peripheral(otg, 1);
- otg->state = OTG_STATE_B_PERIPHERAL;
+ } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ msm_chg_detect_work(&motg->chg_work.work);
+ break;
+ case USB_CHG_STATE_DETECTED:
+ switch (motg->chg_type) {
+ case USB_DCP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ break;
+ case USB_CDP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ case USB_SDP_CHARGER:
+ msm_otg_notify_charger(motg, IUNIT);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ /*
+ * If charger detection work is pending, decrement
+ * the pm usage counter to balance with the one that
+ * is incremented in charger detection work.
+ */
+ if (cancel_delayed_work_sync(&motg->chg_work)) {
+ pm_runtime_put_sync(otg->dev);
+ msm_otg_reset(otg);
+ }
+ msm_otg_notify_charger(motg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
}
pm_runtime_put_sync(otg->dev);
break;
@@ -643,7 +1009,10 @@ static void msm_otg_sm_work(struct work_struct *w)
dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
if (!test_bit(B_SESS_VLD, &motg->inputs) ||
!test_bit(ID, &motg->inputs)) {
+ msm_otg_notify_charger(motg, 0);
msm_otg_start_peripheral(otg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
otg->state = OTG_STATE_B_IDLE;
msm_otg_reset(otg);
schedule_work(w);
@@ -935,6 +1304,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
writel(0, USB_OTGSC);
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+ INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
"msm_otg", motg);
if (ret) {
@@ -945,6 +1315,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
otg->init = msm_otg_reset;
otg->set_host = msm_otg_set_host;
otg->set_peripheral = msm_otg_set_peripheral;
+ otg->set_power = msm_otg_set_power;
otg->io_ops = &msm_otg_io_ops;
@@ -1003,6 +1374,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
return -EBUSY;
msm_otg_debugfs_cleanup();
+ cancel_delayed_work_sync(&motg->chg_work);
cancel_work_sync(&motg->sm_work);
pm_runtime_resume(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 31ef185..00311fe 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -54,6 +54,64 @@ enum otg_control_type {
};
/**
+ * PHY used in
+ *
+ * INVALID_PHY Unsupported PHY
+ * CI_45NM_INTEGRATED_PHY Chipidea 45nm integrated PHY
+ * SNPS_28NM_INTEGRATED_PHY Synopsis 28nm integrated PHY
+ *
+ */
+enum msm_usb_phy_type {
+ INVALID_PHY = 0,
+ CI_45NM_INTEGRATED_PHY,
+ SNPS_28NM_INTEGRATED_PHY,
+};
+
+#define IDEV_CHG_MAX 1500
+#define IUNIT 100
+
+/**
+ * Different states involved in USB charger detection.
+ *
+ * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
+ * process is not yet started.
+ * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
+ * USB_CHG_STATE_DCD_DONE Data pin contact is detected.
+ * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
+ * between SDP and DCP/CDP).
+ * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
+ * between DCP and CDP).
+ * USB_CHG_STATE_DETECTED USB charger type is determined.
+ *
+ */
+enum usb_chg_state {
+ USB_CHG_STATE_UNDEFINED = 0,
+ USB_CHG_STATE_WAIT_FOR_DCD,
+ USB_CHG_STATE_DCD_DONE,
+ USB_CHG_STATE_PRIMARY_DONE,
+ USB_CHG_STATE_SECONDARY_DONE,
+ USB_CHG_STATE_DETECTED,
+};
+
+/**
+ * USB charger types
+ *
+ * USB_INVALID_CHARGER Invalid USB charger.
+ * USB_SDP_CHARGER Standard downstream port. Refers to a downstream port
+ * on USB2.0 compliant host/hub.
+ * USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
+ * USB_CDP_CHARGER Charging downstream port. Enumeration can happen and
+ * IDEV_CHG_MAX can be drawn irrespective of USB state.
+ *
+ */
+enum usb_chg_type {
+ USB_INVALID_CHARGER = 0,
+ USB_SDP_CHARGER,
+ USB_DCP_CHARGER,
+ USB_CDP_CHARGER,
+};
+
+/**
* struct msm_otg_platform_data - platform device data
* for msm_otg driver.
* @phy_init_seq: PHY configuration sequence. val, reg pairs
@@ -74,6 +132,7 @@ struct msm_otg_platform_data {
enum usb_mode_type mode;
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
+ enum msm_usb_phy_type phy_type;
void (*setup_gpio)(enum usb_otg_state state);
char *pclk_src_name;
};
@@ -93,6 +152,12 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
+ * @cur_power: The amount of mA available from downstream port.
+ * @chg_work: Charger detection work.
+ * @chg_state: The state of charger detection process.
+ * @chg_type: The type of charger attached.
+ * @dcd_retires: The retry count used to track Data contact
+ * detection process.
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -110,6 +175,11 @@ struct msm_otg {
struct work_struct sm_work;
atomic_t in_lpm;
int async_int;
+ unsigned cur_power;
+ struct delayed_work chg_work;
+ enum usb_chg_state chg_state;
+ enum usb_chg_type chg_type;
+ u8 dcd_retries;
};
#endif
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V2 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains
[not found] ` <1304318192-24374-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-02 6:36 ` Pavankumar Kondeti
0 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 6:36 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
davidb-sgV2jX0FEOL9JmXXK+q4OQ, sshtylyov-Igf4POYTYCDQT0dZR+AlfA,
Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Pavankumar Kondeti <pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/usb/otg/msm_otg.c | 190 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 189 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 526a650..66a1b7c 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -38,6 +38,7 @@
#include <linux/usb/hcd.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
@@ -45,6 +46,171 @@
#define DRIVER_NAME "msm_otg"
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
+
+#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
+#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
+#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
+#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
+#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
+#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
+#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+
+static struct regulator *hsusb_3p3;
+static struct regulator *hsusb_1p8;
+static struct regulator *hsusb_vddcx;
+
+static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
+{
+ int ret = 0;
+
+ if (init) {
+ hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+ if (IS_ERR(hsusb_vddcx)) {
+ dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+ return PTR_ERR(hsusb_vddcx);
+ }
+
+ ret = regulator_set_voltage(hsusb_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage"
+ "for hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ return ret;
+ }
+
+ ret = regulator_enable(hsusb_vddcx);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ }
+ } else {
+ ret = regulator_set_voltage(hsusb_vddcx, 0,
+ USB_PHY_VDD_DIG_VOL_MIN);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage"
+ "for hsusb vddcx\n");
+ return ret;
+ }
+ ret = regulator_disable(hsusb_vddcx);
+ if (ret)
+ dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
+
+ regulator_put(hsusb_vddcx);
+ }
+
+ return ret;
+}
+
+static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
+{
+ int rc = 0;
+
+ if (init) {
+ hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
+ if (IS_ERR(hsusb_3p3)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
+ return PTR_ERR(hsusb_3p3);
+ }
+
+ rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
+ USB_PHY_3P3_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level for"
+ "hsusb 3p3\n");
+ goto put_3p3;
+ }
+ rc = regulator_enable(hsusb_3p3);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
+ goto put_3p3;
+ }
+ hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
+ if (IS_ERR(hsusb_1p8)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
+ rc = PTR_ERR(hsusb_1p8);
+ goto disable_3p3;
+ }
+ rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
+ USB_PHY_1P8_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level for"
+ "hsusb 1p8\n");
+ goto put_1p8;
+ }
+ rc = regulator_enable(hsusb_1p8);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
+ goto put_1p8;
+ }
+
+ return 0;
+ }
+
+ regulator_disable(hsusb_1p8);
+put_1p8:
+ regulator_put(hsusb_1p8);
+disable_3p3:
+ regulator_disable(hsusb_3p3);
+put_3p3:
+ regulator_put(hsusb_3p3);
+ return rc;
+}
+
+static int msm_hsusb_ldo_set_mode(int on)
+{
+ int ret = 0;
+
+ if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
+ pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
+ pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (on) {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator:"
+ "HSUSB_1p8\n", __func__);
+ return ret;
+ }
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator:"
+ "HSUSB_3p3\n", __func__);
+ regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ return ret;
+ }
+ } else {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator:"
+ "HSUSB_1p8\n", __func__);
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator:"
+ "HSUSB_3p3\n", __func__);
+ }
+
+ pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+ return ret < 0 ? ret : 0;
+}
+
static int ulpi_read(struct otg_transceiver *otg, u32 reg)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -353,7 +519,6 @@ static int msm_otg_resume(struct msm_otg *motg)
if (!IS_ERR(motg->pclk_src))
clk_enable(motg->pclk_src);
- clk_enable(motg->pclk);
clk_enable(motg->clk);
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -1297,6 +1462,24 @@ static int __init msm_otg_probe(struct platform_device *pdev)
clk_enable(motg->clk);
clk_enable(motg->pclk);
+
+ ret = msm_hsusb_init_vddcx(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+ goto free_regs;
+ }
+
+ ret = msm_hsusb_ldo_init(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+ goto vddcx_exit;
+ }
+ ret = msm_hsusb_ldo_set_mode(1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+ goto ldo_exit;
+ }
+
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -1345,6 +1528,10 @@ free_irq:
disable_clks:
clk_disable(motg->pclk);
clk_disable(motg->clk);
+ldo_exit:
+ msm_hsusb_ldo_init(motg, 0);
+vddcx_exit:
+ msm_hsusb_init_vddcx(motg, 0);
free_regs:
iounmap(motg->regs);
put_core_clk:
@@ -1409,6 +1596,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->pclk_src);
clk_put(motg->pclk_src);
}
+ msm_hsusb_ldo_init(motg, 0);
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V2 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960
2011-05-02 6:36 ` [PATCH V2 0/5] USB Charging, PHY init and " Pavankumar Kondeti
` (3 preceding siblings ...)
[not found] ` <1304318192-24374-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-02 6:36 ` Pavankumar Kondeti
2011-05-02 12:22 ` Sergei Shtylyov
4 siblings, 1 reply; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 6:36 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, davidb, sshtylyov, Pavankumar Kondeti
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 64 ++++++++++++++++++++++++++++++++------
include/linux/usb/msm_hsusb_hw.h | 2 +
2 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 66a1b7c..52853fd 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -163,6 +163,32 @@ put_3p3:
return rc;
}
+#ifdef CONFIG_PM_SLEEP
+#define USB_PHY_SUSP_DIG_VOL 500000
+static int msm_hsusb_config_vddcx(int high)
+{
+ int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+ int min_vol;
+ int ret;
+
+ if (high)
+ min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+ else
+ min_vol = USB_PHY_SUSP_DIG_VOL;
+
+ ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+ if (ret) {
+ pr_err("%s: unable to set the voltage for regulator"
+ "HSUSB_VDDCX\n", __func__);
+ return ret;
+ }
+
+ pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+ return ret;
+}
+#endif
+
static int msm_hsusb_ldo_set_mode(int on)
{
int ret = 0;
@@ -434,27 +460,28 @@ static int msm_otg_suspend(struct msm_otg *motg)
disable_irq(motg->irq);
/*
+ * Chipidea 45-nm PHY suspend sequence:
+ *
* Interrupt Latch Register auto-clear feature is not present
* in all PHY versions. Latch register is clear on read type.
* Clear latch register to avoid spurious wakeup from
* low power mode (LPM).
- */
- ulpi_read(otg, 0x14);
-
- /*
+ *
* PHY comparators are disabled when PHY enters into low power
* mode (LPM). Keep PHY comparators ON in LPM only when we expect
* VBUS/Id notifications from USB PHY. Otherwise turn off USB
* PHY comparators. This save significant amount of power.
- */
- if (pdata->otg_control == OTG_PHY_CONTROL)
- ulpi_write(otg, 0x01, 0x30);
-
- /*
+ *
* PLL is not turned off when PHY enters into low power mode (LPM).
* Disable PLL for maximum power savings.
*/
- ulpi_write(otg, 0x08, 0x09);
+
+ if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
+ ulpi_read(otg, 0x14);
+ if (pdata->otg_control == OTG_PHY_CONTROL)
+ ulpi_write(otg, 0x01, 0x30);
+ ulpi_write(otg, 0x08, 0x09);
+ }
/*
* PHY may take some time or even fail to enter into low power
@@ -485,6 +512,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
*/
writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL)
+ writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
+
clk_disable(motg->pclk);
clk_disable(motg->clk);
if (motg->core_clk)
@@ -493,6 +524,12 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (!IS_ERR(motg->pclk_src))
clk_disable(motg->pclk_src);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_set_mode(0);
+ msm_hsusb_config_vddcx(0);
+ }
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -523,6 +560,13 @@ static int msm_otg_resume(struct msm_otg *motg)
if (motg->core_clk)
clk_enable(motg->core_clk);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_set_mode(1);
+ msm_hsusb_config_vddcx(1);
+ writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
+ }
+
temp = readl(USB_USBCMD);
temp &= ~ASYNC_INTR_CTRL;
temp &= ~ULPI_STP_CTRL;
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 7d1babb..6e97a2d 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
#define USB_PORTSC (MSM_USB_BASE + 0x0184)
#define USB_OTGSC (MSM_USB_BASE + 0x01A4)
#define USB_USBMODE (MSM_USB_BASE + 0x01A8)
+#define USB_PHY_CTRL (MSM_USB_BASE + 0x0240)
#define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148)
@@ -42,6 +43,7 @@
#define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */
#define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */
+#define PHY_RETEN (1 << 1) /* PHY retention enable/disable */
/* OTG definitions */
#define OTGSC_INTSTS_MASK (0x7f << 16)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V3 0/5] USB Charging, PHY init and suspend support for MSM8960
[not found] ` <1303977693-18389-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-02 9:58 ` Pavankumar Kondeti
[not found] ` <1304330325-21982-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
` (2 more replies)
0 siblings, 3 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 9:58 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
davidb-sgV2jX0FEOL9JmXXK+q4OQ, sshtylyov-Igf4POYTYCDQT0dZR+AlfA,
Pavankumar Kondeti
This patch series adds PHY based charging detection, PHY initialization and
suspend support for MSM8960 target.
Changelog
- V3
- The third patch in this series unknowingly turning off pclk in resume. Fix
it.
- add "msm" in commit prefix for 2nd patch.
- V2
- logical AND operator is used instead of bitwiese AND for testing flags.
- Fixed error path and label names as per Sergei's comments.
- Fixed a typo mistake (s/phy_type/otg_control) pointed out by Sergei.
- Changed a never-changed-variable into a macro.
Anji jonnala (3):
USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
USB: OTG: msm: vote for dayatona fabric clock
USB: OTG: msm: Configure PHY Analog and Digital voltage domains
Pavankumar Kondeti (2):
USB: OTG: msm: Implement charger detection
USB: OTG: msm: Add PHY suspend support for MSM8960
drivers/usb/gadget/ci13xxx_msm.c | 3 +-
drivers/usb/gadget/ci13xxx_udc.c | 21 ++
drivers/usb/gadget/ci13xxx_udc.h | 3 +
drivers/usb/otg/msm_otg.c | 670 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 79 +++++-
include/linux/usb/msm_hsusb_hw.h | 2 +
6 files changed, 758 insertions(+), 20 deletions(-)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH V3 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
[not found] ` <1304330325-21982-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-02 9:58 ` Pavankumar Kondeti
2011-05-02 9:58 ` [PATCH V3 2/5] USB: OTG: msm: vote for dayatona fabric clock Pavankumar Kondeti
2011-05-02 9:58 ` [PATCH V3 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
2 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 9:58 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
davidb-sgV2jX0FEOL9JmXXK+q4OQ, sshtylyov-Igf4POYTYCDQT0dZR+AlfA,
Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
ITC (Interrupt Threshold Control) field is to set the maximum rate at which
the device controller will issue interrupts. The maximum interrupt interval
is measured in micro frames. Valid values are 0, 1, 2, 4, 8, 16, 32, 64.
The default value is 8 micro frames. Set ITC to zero for MSM to gain
performance.
Signed-off-by: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Pavankumar Kondeti <pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/usb/gadget/ci13xxx_msm.c | 3 ++-
drivers/usb/gadget/ci13xxx_udc.c | 11 +++++++++++
drivers/usb/gadget/ci13xxx_udc.h | 3 +++
3 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 139ac94..aa8319b 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -64,7 +64,8 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
- CI13XXX_DISABLE_STREAMING,
+ CI13XXX_DISABLE_STREAMING |
+ CI13XXX_ZERO_ITC,
.notify_event = ci13xxx_msm_notify_event,
};
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index e09178b..15857e0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -318,6 +318,17 @@ static int hw_device_reset(struct ci13xxx *udc)
hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
+ /*
+ * ITC (Interrupt Threshold Control) field is to set the maximum
+ * rate at which the device controller will issue interrupts.
+ * The maximum interrupt interval measured in micro frames.
+ * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
+ * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
+ * can be set to lesser value to gain performance.
+ */
+ if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
+ hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
+
if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
pr_err("cannot enter in device mode");
pr_err("lpm = %i", hw_bank.lpm);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 2370777..a230325 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -108,6 +108,7 @@ struct ci13xxx_udc_driver {
#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
#define CI13XXX_PULLUP_ON_VBUS BIT(2)
#define CI13XXX_DISABLE_STREAMING BIT(3)
+#define CI13XXX_ZERO_ITC BIT(4)
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_STOPPED_EVENT 1
@@ -189,6 +190,8 @@ struct ci13xxx {
#define USBMODE_CM_HOST (0x03UL << 0)
#define USBMODE_SLOM BIT(3)
#define USBMODE_SDIS BIT(4)
+#define USBCMD_ITC(n) (n << 16) /* n = 0, 1, 2, 4, 8, 16, 32, 64 */
+#define USBCMD_ITC_MASK (0xFF << 16)
/* ENDPTCTRL */
#define ENDPTCTRL_RXS BIT(0)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V3 2/5] USB: OTG: msm: vote for dayatona fabric clock
[not found] ` <1304330325-21982-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-02 9:58 ` [PATCH V3 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
@ 2011-05-02 9:58 ` Pavankumar Kondeti
2011-05-02 9:58 ` [PATCH V3 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
2 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 9:58 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
davidb-sgV2jX0FEOL9JmXXK+q4OQ, sshtylyov-Igf4POYTYCDQT0dZR+AlfA,
Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
HSUSB core clock is derived from daytona fabric clock and for
HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
cannot tolerate daytona fabric clock change in the middle of HSUSB
operational, vote for maximum Daytona fabric clock
while usb is operational
Signed-off-by: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Pavankumar Kondeti <pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/usb/otg/msm_otg.c | 37 +++++++++++++++++++++++++++++++++++--
include/linux/usb/msm_hsusb.h | 7 +++++--
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 2965986..cfbb606 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -324,6 +324,9 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src))
+ clk_disable(motg->pclk_src);
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -347,6 +350,9 @@ static int msm_otg_resume(struct msm_otg *motg)
if (!atomic_read(&motg->in_lpm))
return 0;
+ if (!IS_ERR(motg->pclk_src))
+ clk_enable(motg->pclk_src);
+
clk_enable(motg->pclk);
clk_enable(motg->clk);
if (motg->core_clk)
@@ -862,12 +868,31 @@ static int __init msm_otg_probe(struct platform_device *pdev)
ret = PTR_ERR(motg->clk);
goto put_phy_reset_clk;
}
+ clk_set_rate(motg->clk, 60000000);
+
+ /*
+ * If USB Core is running its protocol engine based on CORE CLK,
+ * CORE CLK must be running at >55Mhz for correct HSUSB
+ * operation and USB core cannot tolerate frequency changes on
+ * CORE CLK. For such USB cores, vote for maximum clk frequency
+ * on pclk source
+ */
+ if (motg->pdata->pclk_src_name) {
+ motg->pclk_src = clk_get(&pdev->dev,
+ motg->pdata->pclk_src_name);
+ if (IS_ERR(motg->pclk_src))
+ goto put_clk;
+ clk_set_rate(motg->pclk_src, INT_MAX);
+ clk_enable(motg->pclk_src);
+ } else
+ motg->pclk_src = ERR_PTR(-ENOENT);
+
motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
if (IS_ERR(motg->pclk)) {
dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
ret = PTR_ERR(motg->pclk);
- goto put_clk;
+ goto put_pclk_src;
}
/*
@@ -954,7 +979,11 @@ free_regs:
put_core_clk:
if (motg->core_clk)
clk_put(motg->core_clk);
- clk_put(motg->pclk);
+put_pclk_src:
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
put_clk:
clk_put(motg->clk);
put_phy_reset_clk:
@@ -1004,6 +1033,10 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->clk);
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 3657403..31ef185 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -64,7 +64,8 @@ enum otg_control_type {
* @otg_control: OTG switch controlled by user/Id pin
* @default_mode: Default operational mode. Applicable only if
* OTG switch is controller by user.
- *
+ * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k
+ * dfab_usb_hs_clk in case of 8660 and 8960.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -74,6 +75,7 @@ struct msm_otg_platform_data {
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
void (*setup_gpio)(enum usb_otg_state state);
+ char *pclk_src_name;
};
/**
@@ -83,6 +85,7 @@ struct msm_otg_platform_data {
* @irq: IRQ number assigned for HSUSB controller.
* @clk: clock struct of usb_hs_clk.
* @pclk: clock struct of usb_hs_pclk.
+ * @pclk_src: pclk source for voting.
* @phy_reset_clk: clock struct of usb_phy_clk.
* @core_clk: clock struct of usb_hs_core_clk.
* @regs: ioremapped register base address.
@@ -90,7 +93,6 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
- *
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -98,6 +100,7 @@ struct msm_otg {
int irq;
struct clk *clk;
struct clk *pclk;
+ struct clk *pclk_src;
struct clk *phy_reset_clk;
struct clk *core_clk;
void __iomem *regs;
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V3 3/5] USB: OTG: msm: Implement charger detection
[not found] ` <1304330325-21982-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-02 9:58 ` [PATCH V3 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
2011-05-02 9:58 ` [PATCH V3 2/5] USB: OTG: msm: vote for dayatona fabric clock Pavankumar Kondeti
@ 2011-05-02 9:58 ` Pavankumar Kondeti
2 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 9:58 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
davidb-sgV2jX0FEOL9JmXXK+q4OQ, sshtylyov-Igf4POYTYCDQT0dZR+AlfA,
Pavankumar Kondeti
Implement good battery algorithm defined in the battery charging V1.2 spec
for detecting different charging ports. USB hardware is put into low power
mode when connected to a dedicated charging port. vbus_draw and set_power
methods are implemented for determining the allowed current from Host in
different states (un-configured/suspend/configured).
The charger block is implemented using vendor specific registers and the
PHY used in MSM8960(28nm PHY) different from older targets like MSM8x60
and MSM7x30(45nm PHY). The PHY vendor and product id registers are not
implemented in the above chipsets. Hence PHY type is passed via platform
data.
Signed-off-by: Pavankumar Kondeti <pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/usb/gadget/ci13xxx_udc.c | 10 +
drivers/usb/otg/msm_otg.c | 380 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 72 +++++++-
3 files changed, 457 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 15857e0..6000714 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2508,6 +2508,15 @@ out:
return ret;
}
+static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+ struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+
+ if (udc->transceiver)
+ return otg_set_power(udc->transceiver, mA);
+ return -ENOTSUPP;
+}
+
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
@@ -2516,6 +2525,7 @@ out:
static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci13xxx_vbus_session,
.wakeup = ci13xxx_wakeup,
+ .vbus_draw = ci13xxx_vbus_draw,
};
/**
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index cfbb606..526a650 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -409,6 +409,33 @@ skip_phy_resume:
}
#endif
+static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
+{
+ if (motg->cur_power == mA)
+ return;
+
+ /* TODO: Notify PMIC about available current */
+ dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
+ motg->cur_power = mA;
+}
+
+static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+ struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+ /*
+ * Gadget driver uses set_power method to notify about the
+ * available current based on suspend/configured states.
+ *
+ * IDEV_CHG can be drawn irrespective of suspend/un-configured
+ * states when CDP/ACA is connected.
+ */
+ if (motg->chg_type == USB_SDP_CHARGER)
+ msm_otg_notify_charger(motg, mA);
+
+ return 0;
+}
+
static void msm_otg_start_host(struct otg_transceiver *otg, int on)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -563,6 +590,306 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg,
return 0;
}
+static bool msm_chg_check_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* put it in host mode for enabling D- source */
+ chg_det &= ~(1 << 2);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DM as current source, DP as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x8, 0x85);
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DP as current source, DM as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 line_state;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x15);
+ ret = !(line_state & 1);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x87);
+ ret = line_state & 2;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_disable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ chg_det &= ~(1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ ulpi_write(otg, 0x10, 0x86);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_enable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn on D+ current source */
+ chg_det |= (1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Data contact detection enable */
+ ulpi_write(otg, 0x10, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_on(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ /* put the controller in non-driving mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ udelay(100);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_off(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ break;
+ default:
+ break;
+ }
+
+ /* put the controller in normal mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+}
+
+#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
+#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
+static void msm_chg_detect_work(struct work_struct *w)
+{
+ struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
+ struct otg_transceiver *otg = &motg->otg;
+ bool is_dcd, tmout, vout;
+ unsigned long delay;
+
+ dev_dbg(otg->dev, "chg detection work\n");
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ pm_runtime_get_sync(otg->dev);
+ msm_chg_block_on(motg);
+ msm_chg_enable_dcd(motg);
+ motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
+ motg->dcd_retries = 0;
+ delay = MSM_CHG_DCD_POLL_TIME;
+ break;
+ case USB_CHG_STATE_WAIT_FOR_DCD:
+ is_dcd = msm_chg_check_dcd(motg);
+ tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
+ if (is_dcd || tmout) {
+ msm_chg_disable_dcd(motg);
+ msm_chg_enable_primary_det(motg);
+ delay = MSM_CHG_PRIMARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_DCD_DONE;
+ } else {
+ delay = MSM_CHG_DCD_POLL_TIME;
+ }
+ break;
+ case USB_CHG_STATE_DCD_DONE:
+ vout = msm_chg_check_primary_det(motg);
+ if (vout) {
+ msm_chg_enable_secondary_det(motg);
+ delay = MSM_CHG_SECONDARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
+ } else {
+ motg->chg_type = USB_SDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ delay = 0;
+ }
+ break;
+ case USB_CHG_STATE_PRIMARY_DONE:
+ vout = msm_chg_check_secondary_det(motg);
+ if (vout)
+ motg->chg_type = USB_DCP_CHARGER;
+ else
+ motg->chg_type = USB_CDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
+ /* fall through */
+ case USB_CHG_STATE_SECONDARY_DONE:
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ case USB_CHG_STATE_DETECTED:
+ msm_chg_block_off(motg);
+ dev_dbg(otg->dev, "charger = %d\n", motg->chg_type);
+ schedule_work(&motg->sm_work);
+ return;
+ default:
+ return;
+ }
+
+ schedule_delayed_work(&motg->chg_work, delay);
+}
+
/*
* We support OTG, Peripheral only and Host only configurations. In case
* of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
@@ -633,9 +960,48 @@ static void msm_otg_sm_work(struct work_struct *w)
writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
msm_otg_start_host(otg, 1);
otg->state = OTG_STATE_A_HOST;
- } else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) {
- msm_otg_start_peripheral(otg, 1);
- otg->state = OTG_STATE_B_PERIPHERAL;
+ } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ msm_chg_detect_work(&motg->chg_work.work);
+ break;
+ case USB_CHG_STATE_DETECTED:
+ switch (motg->chg_type) {
+ case USB_DCP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ break;
+ case USB_CDP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ case USB_SDP_CHARGER:
+ msm_otg_notify_charger(motg, IUNIT);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ /*
+ * If charger detection work is pending, decrement
+ * the pm usage counter to balance with the one that
+ * is incremented in charger detection work.
+ */
+ if (cancel_delayed_work_sync(&motg->chg_work)) {
+ pm_runtime_put_sync(otg->dev);
+ msm_otg_reset(otg);
+ }
+ msm_otg_notify_charger(motg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
}
pm_runtime_put_sync(otg->dev);
break;
@@ -643,7 +1009,10 @@ static void msm_otg_sm_work(struct work_struct *w)
dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
if (!test_bit(B_SESS_VLD, &motg->inputs) ||
!test_bit(ID, &motg->inputs)) {
+ msm_otg_notify_charger(motg, 0);
msm_otg_start_peripheral(otg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
otg->state = OTG_STATE_B_IDLE;
msm_otg_reset(otg);
schedule_work(w);
@@ -935,6 +1304,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
writel(0, USB_OTGSC);
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+ INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
"msm_otg", motg);
if (ret) {
@@ -945,6 +1315,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
otg->init = msm_otg_reset;
otg->set_host = msm_otg_set_host;
otg->set_peripheral = msm_otg_set_peripheral;
+ otg->set_power = msm_otg_set_power;
otg->io_ops = &msm_otg_io_ops;
@@ -1003,6 +1374,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
return -EBUSY;
msm_otg_debugfs_cleanup();
+ cancel_delayed_work_sync(&motg->chg_work);
cancel_work_sync(&motg->sm_work);
pm_runtime_resume(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 31ef185..00311fe 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -54,6 +54,64 @@ enum otg_control_type {
};
/**
+ * PHY used in
+ *
+ * INVALID_PHY Unsupported PHY
+ * CI_45NM_INTEGRATED_PHY Chipidea 45nm integrated PHY
+ * SNPS_28NM_INTEGRATED_PHY Synopsis 28nm integrated PHY
+ *
+ */
+enum msm_usb_phy_type {
+ INVALID_PHY = 0,
+ CI_45NM_INTEGRATED_PHY,
+ SNPS_28NM_INTEGRATED_PHY,
+};
+
+#define IDEV_CHG_MAX 1500
+#define IUNIT 100
+
+/**
+ * Different states involved in USB charger detection.
+ *
+ * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
+ * process is not yet started.
+ * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
+ * USB_CHG_STATE_DCD_DONE Data pin contact is detected.
+ * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
+ * between SDP and DCP/CDP).
+ * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
+ * between DCP and CDP).
+ * USB_CHG_STATE_DETECTED USB charger type is determined.
+ *
+ */
+enum usb_chg_state {
+ USB_CHG_STATE_UNDEFINED = 0,
+ USB_CHG_STATE_WAIT_FOR_DCD,
+ USB_CHG_STATE_DCD_DONE,
+ USB_CHG_STATE_PRIMARY_DONE,
+ USB_CHG_STATE_SECONDARY_DONE,
+ USB_CHG_STATE_DETECTED,
+};
+
+/**
+ * USB charger types
+ *
+ * USB_INVALID_CHARGER Invalid USB charger.
+ * USB_SDP_CHARGER Standard downstream port. Refers to a downstream port
+ * on USB2.0 compliant host/hub.
+ * USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
+ * USB_CDP_CHARGER Charging downstream port. Enumeration can happen and
+ * IDEV_CHG_MAX can be drawn irrespective of USB state.
+ *
+ */
+enum usb_chg_type {
+ USB_INVALID_CHARGER = 0,
+ USB_SDP_CHARGER,
+ USB_DCP_CHARGER,
+ USB_CDP_CHARGER,
+};
+
+/**
* struct msm_otg_platform_data - platform device data
* for msm_otg driver.
* @phy_init_seq: PHY configuration sequence. val, reg pairs
@@ -74,6 +132,7 @@ struct msm_otg_platform_data {
enum usb_mode_type mode;
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
+ enum msm_usb_phy_type phy_type;
void (*setup_gpio)(enum usb_otg_state state);
char *pclk_src_name;
};
@@ -93,6 +152,12 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
+ * @cur_power: The amount of mA available from downstream port.
+ * @chg_work: Charger detection work.
+ * @chg_state: The state of charger detection process.
+ * @chg_type: The type of charger attached.
+ * @dcd_retires: The retry count used to track Data contact
+ * detection process.
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -110,6 +175,11 @@ struct msm_otg {
struct work_struct sm_work;
atomic_t in_lpm;
int async_int;
+ unsigned cur_power;
+ struct delayed_work chg_work;
+ enum usb_chg_state chg_state;
+ enum usb_chg_type chg_type;
+ u8 dcd_retries;
};
#endif
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V3 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains
2011-05-02 9:58 ` [PATCH V3 0/5] USB Charging, PHY init and " Pavankumar Kondeti
[not found] ` <1304330325-21982-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-02 9:58 ` Pavankumar Kondeti
2011-05-02 9:58 ` [PATCH V3 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
2 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 9:58 UTC (permalink / raw)
To: greg, linux-usb
Cc: linux-arm-msm, davidb, sshtylyov, Anji jonnala,
Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 189 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 189 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 526a650..9711a74 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -38,6 +38,7 @@
#include <linux/usb/hcd.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
@@ -45,6 +46,171 @@
#define DRIVER_NAME "msm_otg"
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
+
+#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
+#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
+#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
+#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
+#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
+#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
+#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+
+static struct regulator *hsusb_3p3;
+static struct regulator *hsusb_1p8;
+static struct regulator *hsusb_vddcx;
+
+static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
+{
+ int ret = 0;
+
+ if (init) {
+ hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+ if (IS_ERR(hsusb_vddcx)) {
+ dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+ return PTR_ERR(hsusb_vddcx);
+ }
+
+ ret = regulator_set_voltage(hsusb_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage"
+ "for hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ return ret;
+ }
+
+ ret = regulator_enable(hsusb_vddcx);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ }
+ } else {
+ ret = regulator_set_voltage(hsusb_vddcx, 0,
+ USB_PHY_VDD_DIG_VOL_MIN);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage"
+ "for hsusb vddcx\n");
+ return ret;
+ }
+ ret = regulator_disable(hsusb_vddcx);
+ if (ret)
+ dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
+
+ regulator_put(hsusb_vddcx);
+ }
+
+ return ret;
+}
+
+static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
+{
+ int rc = 0;
+
+ if (init) {
+ hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
+ if (IS_ERR(hsusb_3p3)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
+ return PTR_ERR(hsusb_3p3);
+ }
+
+ rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
+ USB_PHY_3P3_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level for"
+ "hsusb 3p3\n");
+ goto put_3p3;
+ }
+ rc = regulator_enable(hsusb_3p3);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
+ goto put_3p3;
+ }
+ hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
+ if (IS_ERR(hsusb_1p8)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
+ rc = PTR_ERR(hsusb_1p8);
+ goto disable_3p3;
+ }
+ rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
+ USB_PHY_1P8_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level for"
+ "hsusb 1p8\n");
+ goto put_1p8;
+ }
+ rc = regulator_enable(hsusb_1p8);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
+ goto put_1p8;
+ }
+
+ return 0;
+ }
+
+ regulator_disable(hsusb_1p8);
+put_1p8:
+ regulator_put(hsusb_1p8);
+disable_3p3:
+ regulator_disable(hsusb_3p3);
+put_3p3:
+ regulator_put(hsusb_3p3);
+ return rc;
+}
+
+static int msm_hsusb_ldo_set_mode(int on)
+{
+ int ret = 0;
+
+ if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
+ pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
+ pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (on) {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator:"
+ "HSUSB_1p8\n", __func__);
+ return ret;
+ }
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator:"
+ "HSUSB_3p3\n", __func__);
+ regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ return ret;
+ }
+ } else {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator:"
+ "HSUSB_1p8\n", __func__);
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator:"
+ "HSUSB_3p3\n", __func__);
+ }
+
+ pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+ return ret < 0 ? ret : 0;
+}
+
static int ulpi_read(struct otg_transceiver *otg, u32 reg)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -1297,6 +1463,24 @@ static int __init msm_otg_probe(struct platform_device *pdev)
clk_enable(motg->clk);
clk_enable(motg->pclk);
+
+ ret = msm_hsusb_init_vddcx(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+ goto free_regs;
+ }
+
+ ret = msm_hsusb_ldo_init(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+ goto vddcx_exit;
+ }
+ ret = msm_hsusb_ldo_set_mode(1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+ goto ldo_exit;
+ }
+
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -1345,6 +1529,10 @@ free_irq:
disable_clks:
clk_disable(motg->pclk);
clk_disable(motg->clk);
+ldo_exit:
+ msm_hsusb_ldo_init(motg, 0);
+vddcx_exit:
+ msm_hsusb_init_vddcx(motg, 0);
free_regs:
iounmap(motg->regs);
put_core_clk:
@@ -1409,6 +1597,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->pclk_src);
clk_put(motg->pclk_src);
}
+ msm_hsusb_ldo_init(motg, 0);
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V3 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960
2011-05-02 9:58 ` [PATCH V3 0/5] USB Charging, PHY init and " Pavankumar Kondeti
[not found] ` <1304330325-21982-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-02 9:58 ` [PATCH V3 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
@ 2011-05-02 9:58 ` Pavankumar Kondeti
2 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-02 9:58 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, davidb, sshtylyov, Pavankumar Kondeti
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 64 ++++++++++++++++++++++++++++++++------
include/linux/usb/msm_hsusb_hw.h | 2 +
2 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 9711a74..2fc953c 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -163,6 +163,32 @@ put_3p3:
return rc;
}
+#ifdef CONFIG_PM_SLEEP
+#define USB_PHY_SUSP_DIG_VOL 500000
+static int msm_hsusb_config_vddcx(int high)
+{
+ int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+ int min_vol;
+ int ret;
+
+ if (high)
+ min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+ else
+ min_vol = USB_PHY_SUSP_DIG_VOL;
+
+ ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+ if (ret) {
+ pr_err("%s: unable to set the voltage for regulator"
+ "HSUSB_VDDCX\n", __func__);
+ return ret;
+ }
+
+ pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+ return ret;
+}
+#endif
+
static int msm_hsusb_ldo_set_mode(int on)
{
int ret = 0;
@@ -434,27 +460,28 @@ static int msm_otg_suspend(struct msm_otg *motg)
disable_irq(motg->irq);
/*
+ * Chipidea 45-nm PHY suspend sequence:
+ *
* Interrupt Latch Register auto-clear feature is not present
* in all PHY versions. Latch register is clear on read type.
* Clear latch register to avoid spurious wakeup from
* low power mode (LPM).
- */
- ulpi_read(otg, 0x14);
-
- /*
+ *
* PHY comparators are disabled when PHY enters into low power
* mode (LPM). Keep PHY comparators ON in LPM only when we expect
* VBUS/Id notifications from USB PHY. Otherwise turn off USB
* PHY comparators. This save significant amount of power.
- */
- if (pdata->otg_control == OTG_PHY_CONTROL)
- ulpi_write(otg, 0x01, 0x30);
-
- /*
+ *
* PLL is not turned off when PHY enters into low power mode (LPM).
* Disable PLL for maximum power savings.
*/
- ulpi_write(otg, 0x08, 0x09);
+
+ if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
+ ulpi_read(otg, 0x14);
+ if (pdata->otg_control == OTG_PHY_CONTROL)
+ ulpi_write(otg, 0x01, 0x30);
+ ulpi_write(otg, 0x08, 0x09);
+ }
/*
* PHY may take some time or even fail to enter into low power
@@ -485,6 +512,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
*/
writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL)
+ writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
+
clk_disable(motg->pclk);
clk_disable(motg->clk);
if (motg->core_clk)
@@ -493,6 +524,12 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (!IS_ERR(motg->pclk_src))
clk_disable(motg->pclk_src);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_set_mode(0);
+ msm_hsusb_config_vddcx(0);
+ }
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -524,6 +561,13 @@ static int msm_otg_resume(struct msm_otg *motg)
if (motg->core_clk)
clk_enable(motg->core_clk);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_set_mode(1);
+ msm_hsusb_config_vddcx(1);
+ writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
+ }
+
temp = readl(USB_USBCMD);
temp &= ~ASYNC_INTR_CTRL;
temp &= ~ULPI_STP_CTRL;
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 7d1babb..6e97a2d 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
#define USB_PORTSC (MSM_USB_BASE + 0x0184)
#define USB_OTGSC (MSM_USB_BASE + 0x01A4)
#define USB_USBMODE (MSM_USB_BASE + 0x01A8)
+#define USB_PHY_CTRL (MSM_USB_BASE + 0x0240)
#define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148)
@@ -42,6 +43,7 @@
#define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */
#define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */
+#define PHY_RETEN (1 << 1) /* PHY retention enable/disable */
/* OTG definitions */
#define OTGSC_INTSTS_MASK (0x7f << 16)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH V2 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960
2011-05-02 6:36 ` [PATCH V2 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
@ 2011-05-02 12:22 ` Sergei Shtylyov
2011-05-03 5:01 ` Pavan Kondeti
0 siblings, 1 reply; 45+ messages in thread
From: Sergei Shtylyov @ 2011-05-02 12:22 UTC (permalink / raw)
To: Pavankumar Kondeti; +Cc: greg, linux-usb, linux-arm-msm, davidb, sshtylyov
Hello.
On 02-05-2011 10:36, Pavankumar Kondeti wrote:
> Signed-off-by: Pavankumar Kondeti<pkondeti@codeaurora.org>
[...]
> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
> index 66a1b7c..52853fd 100644
> --- a/drivers/usb/otg/msm_otg.c
> +++ b/drivers/usb/otg/msm_otg.c
> @@ -163,6 +163,32 @@ put_3p3:
> return rc;
> }
>
> +#ifdef CONFIG_PM_SLEEP
> +#define USB_PHY_SUSP_DIG_VOL 500000
> +static int msm_hsusb_config_vddcx(int high)
> +{
> + int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
> + int min_vol;
> + int ret;
> +
> + if (high)
> + min_vol = USB_PHY_VDD_DIG_VOL_MIN;
> + else
> + min_vol = USB_PHY_SUSP_DIG_VOL;
> +
> + ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
> + if (ret) {
> + pr_err("%s: unable to set the voltage for regulator"
You missed space after "regulator"...
> + "HSUSB_VDDCX\n", __func__);
> + return ret;
> + }
> +
[...]
WBR, Sergei
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH V2 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960
2011-05-02 12:22 ` Sergei Shtylyov
@ 2011-05-03 5:01 ` Pavan Kondeti
0 siblings, 0 replies; 45+ messages in thread
From: Pavan Kondeti @ 2011-05-03 5:01 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: greg, linux-usb, linux-arm-msm, davidb
On 5/2/2011 5:52 PM, Sergei Shtylyov wrote:
> Hello.
>
> On 02-05-2011 10:36, Pavankumar Kondeti wrote:
>
>> Signed-off-by: Pavankumar Kondeti<pkondeti@codeaurora.org>
> [...]
>
>> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
>> index 66a1b7c..52853fd 100644
>> --- a/drivers/usb/otg/msm_otg.c
>> +++ b/drivers/usb/otg/msm_otg.c
>> @@ -163,6 +163,32 @@ put_3p3:
>> return rc;
>> }
>>
>> +#ifdef CONFIG_PM_SLEEP
>> +#define USB_PHY_SUSP_DIG_VOL 500000
>> +static int msm_hsusb_config_vddcx(int high)
>> +{
>> + int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
>> + int min_vol;
>> + int ret;
>> +
>> + if (high)
>> + min_vol = USB_PHY_VDD_DIG_VOL_MIN;
>> + else
>> + min_vol = USB_PHY_SUSP_DIG_VOL;
>> +
>> + ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
>> + if (ret) {
>> + pr_err("%s: unable to set the voltage for regulator"
>
> You missed space after "regulator"...
Thanks for pointing this out. The other patch (USB: OTG: msm: Configure
PHY Analog and Digital voltage domains) also has missed spaces. I will
fix it in next patch set.
>
>> + "HSUSB_VDDCX\n", __func__);
>> + return ret;
>> + }
>> +
> [...]
>
> WBR, Sergei
Thanks,
Pavan
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH V4 0/5] USB Charging, PHY init and suspend support for MSM8960
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
` (7 preceding siblings ...)
[not found] ` <1303977693-18389-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-03 5:13 ` Pavankumar Kondeti
[not found] ` <1304399633-16120-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
` (4 more replies)
2011-05-04 4:49 ` [PATCH V5 0/4] USB Charging, PHY init and " Pavankumar Kondeti
9 siblings, 5 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-03 5:13 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, davidb, sshtylyov, Pavankumar Kondeti
This patch series adds PHY based charging detection, PHY initialization and
suspend support for MSM8960 target.
Changelog
- V4
- Added missing spaces at the end of line for multi line printk messages.
- V3
- The third patch in this series unknowingly turning off pclk in resume. Fix
it.
- add "msm" in commit prefix for 2nd patch.
- V2
- logical AND operator is used instead of bitwiese AND for testing flags.
- Fixed error path and label names as per Sergei's comments.
- Fixed a typo mistake (s/phy_type/otg_control) pointed out by Sergei.
- Changed a never-changed-variable into a macro.
Anji jonnala (3):
USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
USB: OTG: msm: vote for dayatona fabric clock
USB: OTG: msm: Configure PHY Analog and Digital voltage domains
Pavankumar Kondeti (2):
USB: OTG: msm: Implement charger detection
USB: OTG: msm: Add PHY suspend support for MSM8960
drivers/usb/gadget/ci13xxx_msm.c | 3 +-
drivers/usb/gadget/ci13xxx_udc.c | 21 ++
drivers/usb/gadget/ci13xxx_udc.h | 3 +
drivers/usb/otg/msm_otg.c | 670 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 79 +++++-
include/linux/usb/msm_hsusb_hw.h | 2 +
6 files changed, 758 insertions(+), 20 deletions(-)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH V4 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm
[not found] ` <1304399633-16120-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-03 5:13 ` Pavankumar Kondeti
0 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-03 5:13 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
davidb-sgV2jX0FEOL9JmXXK+q4OQ, sshtylyov-Igf4POYTYCDQT0dZR+AlfA,
Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
ITC (Interrupt Threshold Control) field is to set the maximum rate at which
the device controller will issue interrupts. The maximum interrupt interval
is measured in micro frames. Valid values are 0, 1, 2, 4, 8, 16, 32, 64.
The default value is 8 micro frames. Set ITC to zero for MSM to gain
performance.
Signed-off-by: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Pavankumar Kondeti <pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/usb/gadget/ci13xxx_msm.c | 3 ++-
drivers/usb/gadget/ci13xxx_udc.c | 11 +++++++++++
drivers/usb/gadget/ci13xxx_udc.h | 3 +++
3 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 139ac94..aa8319b 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -64,7 +64,8 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
- CI13XXX_DISABLE_STREAMING,
+ CI13XXX_DISABLE_STREAMING |
+ CI13XXX_ZERO_ITC,
.notify_event = ci13xxx_msm_notify_event,
};
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index e09178b..15857e0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -318,6 +318,17 @@ static int hw_device_reset(struct ci13xxx *udc)
hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE);
hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */
+ /*
+ * ITC (Interrupt Threshold Control) field is to set the maximum
+ * rate at which the device controller will issue interrupts.
+ * The maximum interrupt interval measured in micro frames.
+ * Valid values are 0, 1, 2, 4, 8, 16, 32, 64. The default value is
+ * 8 micro frames. If CPU can handle interrupts at faster rate, ITC
+ * can be set to lesser value to gain performance.
+ */
+ if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
+ hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
+
if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
pr_err("cannot enter in device mode");
pr_err("lpm = %i", hw_bank.lpm);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 2370777..a230325 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -108,6 +108,7 @@ struct ci13xxx_udc_driver {
#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
#define CI13XXX_PULLUP_ON_VBUS BIT(2)
#define CI13XXX_DISABLE_STREAMING BIT(3)
+#define CI13XXX_ZERO_ITC BIT(4)
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_STOPPED_EVENT 1
@@ -189,6 +190,8 @@ struct ci13xxx {
#define USBMODE_CM_HOST (0x03UL << 0)
#define USBMODE_SLOM BIT(3)
#define USBMODE_SDIS BIT(4)
+#define USBCMD_ITC(n) (n << 16) /* n = 0, 1, 2, 4, 8, 16, 32, 64 */
+#define USBCMD_ITC_MASK (0xFF << 16)
/* ENDPTCTRL */
#define ENDPTCTRL_RXS BIT(0)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V4 2/5] USB: OTG: msm: vote for dayatona fabric clock
2011-05-03 5:13 ` [PATCH V4 0/5] USB Charging, PHY init and " Pavankumar Kondeti
[not found] ` <1304399633-16120-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-03 5:13 ` Pavankumar Kondeti
[not found] ` <1304399633-16120-3-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-03 5:13 ` [PATCH V4 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
` (2 subsequent siblings)
4 siblings, 1 reply; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-03 5:13 UTC (permalink / raw)
To: greg, linux-usb
Cc: linux-arm-msm, davidb, sshtylyov, Anji jonnala,
Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
HSUSB core clock is derived from daytona fabric clock and for
HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
cannot tolerate daytona fabric clock change in the middle of HSUSB
operational, vote for maximum Daytona fabric clock
while usb is operational
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 37 +++++++++++++++++++++++++++++++++++--
include/linux/usb/msm_hsusb.h | 7 +++++--
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 2965986..cfbb606 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -324,6 +324,9 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src))
+ clk_disable(motg->pclk_src);
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -347,6 +350,9 @@ static int msm_otg_resume(struct msm_otg *motg)
if (!atomic_read(&motg->in_lpm))
return 0;
+ if (!IS_ERR(motg->pclk_src))
+ clk_enable(motg->pclk_src);
+
clk_enable(motg->pclk);
clk_enable(motg->clk);
if (motg->core_clk)
@@ -862,12 +868,31 @@ static int __init msm_otg_probe(struct platform_device *pdev)
ret = PTR_ERR(motg->clk);
goto put_phy_reset_clk;
}
+ clk_set_rate(motg->clk, 60000000);
+
+ /*
+ * If USB Core is running its protocol engine based on CORE CLK,
+ * CORE CLK must be running at >55Mhz for correct HSUSB
+ * operation and USB core cannot tolerate frequency changes on
+ * CORE CLK. For such USB cores, vote for maximum clk frequency
+ * on pclk source
+ */
+ if (motg->pdata->pclk_src_name) {
+ motg->pclk_src = clk_get(&pdev->dev,
+ motg->pdata->pclk_src_name);
+ if (IS_ERR(motg->pclk_src))
+ goto put_clk;
+ clk_set_rate(motg->pclk_src, INT_MAX);
+ clk_enable(motg->pclk_src);
+ } else
+ motg->pclk_src = ERR_PTR(-ENOENT);
+
motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
if (IS_ERR(motg->pclk)) {
dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
ret = PTR_ERR(motg->pclk);
- goto put_clk;
+ goto put_pclk_src;
}
/*
@@ -954,7 +979,11 @@ free_regs:
put_core_clk:
if (motg->core_clk)
clk_put(motg->core_clk);
- clk_put(motg->pclk);
+put_pclk_src:
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
put_clk:
clk_put(motg->clk);
put_phy_reset_clk:
@@ -1004,6 +1033,10 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->clk);
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 3657403..31ef185 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -64,7 +64,8 @@ enum otg_control_type {
* @otg_control: OTG switch controlled by user/Id pin
* @default_mode: Default operational mode. Applicable only if
* OTG switch is controller by user.
- *
+ * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k
+ * dfab_usb_hs_clk in case of 8660 and 8960.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -74,6 +75,7 @@ struct msm_otg_platform_data {
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
void (*setup_gpio)(enum usb_otg_state state);
+ char *pclk_src_name;
};
/**
@@ -83,6 +85,7 @@ struct msm_otg_platform_data {
* @irq: IRQ number assigned for HSUSB controller.
* @clk: clock struct of usb_hs_clk.
* @pclk: clock struct of usb_hs_pclk.
+ * @pclk_src: pclk source for voting.
* @phy_reset_clk: clock struct of usb_phy_clk.
* @core_clk: clock struct of usb_hs_core_clk.
* @regs: ioremapped register base address.
@@ -90,7 +93,6 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
- *
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -98,6 +100,7 @@ struct msm_otg {
int irq;
struct clk *clk;
struct clk *pclk;
+ struct clk *pclk_src;
struct clk *phy_reset_clk;
struct clk *core_clk;
void __iomem *regs;
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V4 3/5] USB: OTG: msm: Implement charger detection
2011-05-03 5:13 ` [PATCH V4 0/5] USB Charging, PHY init and " Pavankumar Kondeti
[not found] ` <1304399633-16120-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-03 5:13 ` [PATCH V4 2/5] USB: OTG: msm: vote for dayatona fabric clock Pavankumar Kondeti
@ 2011-05-03 5:13 ` Pavankumar Kondeti
2011-05-03 5:13 ` [PATCH V4 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
2011-05-03 5:13 ` [PATCH V4 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
4 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-03 5:13 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, davidb, sshtylyov, Pavankumar Kondeti
Implement good battery algorithm defined in the battery charging V1.2 spec
for detecting different charging ports. USB hardware is put into low power
mode when connected to a dedicated charging port. vbus_draw and set_power
methods are implemented for determining the allowed current from Host in
different states (un-configured/suspend/configured).
The charger block is implemented using vendor specific registers and the
PHY used in MSM8960(28nm PHY) different from older targets like MSM8x60
and MSM7x30(45nm PHY). The PHY vendor and product id registers are not
implemented in the above chipsets. Hence PHY type is passed via platform
data.
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/gadget/ci13xxx_udc.c | 10 +
drivers/usb/otg/msm_otg.c | 380 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 72 +++++++-
3 files changed, 457 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 15857e0..6000714 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2508,6 +2508,15 @@ out:
return ret;
}
+static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+ struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+
+ if (udc->transceiver)
+ return otg_set_power(udc->transceiver, mA);
+ return -ENOTSUPP;
+}
+
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
@@ -2516,6 +2525,7 @@ out:
static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci13xxx_vbus_session,
.wakeup = ci13xxx_wakeup,
+ .vbus_draw = ci13xxx_vbus_draw,
};
/**
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index cfbb606..526a650 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -409,6 +409,33 @@ skip_phy_resume:
}
#endif
+static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
+{
+ if (motg->cur_power == mA)
+ return;
+
+ /* TODO: Notify PMIC about available current */
+ dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
+ motg->cur_power = mA;
+}
+
+static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+ struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+ /*
+ * Gadget driver uses set_power method to notify about the
+ * available current based on suspend/configured states.
+ *
+ * IDEV_CHG can be drawn irrespective of suspend/un-configured
+ * states when CDP/ACA is connected.
+ */
+ if (motg->chg_type == USB_SDP_CHARGER)
+ msm_otg_notify_charger(motg, mA);
+
+ return 0;
+}
+
static void msm_otg_start_host(struct otg_transceiver *otg, int on)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -563,6 +590,306 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg,
return 0;
}
+static bool msm_chg_check_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* put it in host mode for enabling D- source */
+ chg_det &= ~(1 << 2);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DM as current source, DP as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x8, 0x85);
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DP as current source, DM as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 line_state;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x15);
+ ret = !(line_state & 1);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x87);
+ ret = line_state & 2;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_disable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ chg_det &= ~(1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ ulpi_write(otg, 0x10, 0x86);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_enable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn on D+ current source */
+ chg_det |= (1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Data contact detection enable */
+ ulpi_write(otg, 0x10, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_on(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ /* put the controller in non-driving mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ udelay(100);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_off(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ break;
+ default:
+ break;
+ }
+
+ /* put the controller in normal mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+}
+
+#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
+#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
+static void msm_chg_detect_work(struct work_struct *w)
+{
+ struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
+ struct otg_transceiver *otg = &motg->otg;
+ bool is_dcd, tmout, vout;
+ unsigned long delay;
+
+ dev_dbg(otg->dev, "chg detection work\n");
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ pm_runtime_get_sync(otg->dev);
+ msm_chg_block_on(motg);
+ msm_chg_enable_dcd(motg);
+ motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
+ motg->dcd_retries = 0;
+ delay = MSM_CHG_DCD_POLL_TIME;
+ break;
+ case USB_CHG_STATE_WAIT_FOR_DCD:
+ is_dcd = msm_chg_check_dcd(motg);
+ tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
+ if (is_dcd || tmout) {
+ msm_chg_disable_dcd(motg);
+ msm_chg_enable_primary_det(motg);
+ delay = MSM_CHG_PRIMARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_DCD_DONE;
+ } else {
+ delay = MSM_CHG_DCD_POLL_TIME;
+ }
+ break;
+ case USB_CHG_STATE_DCD_DONE:
+ vout = msm_chg_check_primary_det(motg);
+ if (vout) {
+ msm_chg_enable_secondary_det(motg);
+ delay = MSM_CHG_SECONDARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
+ } else {
+ motg->chg_type = USB_SDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ delay = 0;
+ }
+ break;
+ case USB_CHG_STATE_PRIMARY_DONE:
+ vout = msm_chg_check_secondary_det(motg);
+ if (vout)
+ motg->chg_type = USB_DCP_CHARGER;
+ else
+ motg->chg_type = USB_CDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
+ /* fall through */
+ case USB_CHG_STATE_SECONDARY_DONE:
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ case USB_CHG_STATE_DETECTED:
+ msm_chg_block_off(motg);
+ dev_dbg(otg->dev, "charger = %d\n", motg->chg_type);
+ schedule_work(&motg->sm_work);
+ return;
+ default:
+ return;
+ }
+
+ schedule_delayed_work(&motg->chg_work, delay);
+}
+
/*
* We support OTG, Peripheral only and Host only configurations. In case
* of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
@@ -633,9 +960,48 @@ static void msm_otg_sm_work(struct work_struct *w)
writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
msm_otg_start_host(otg, 1);
otg->state = OTG_STATE_A_HOST;
- } else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) {
- msm_otg_start_peripheral(otg, 1);
- otg->state = OTG_STATE_B_PERIPHERAL;
+ } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ msm_chg_detect_work(&motg->chg_work.work);
+ break;
+ case USB_CHG_STATE_DETECTED:
+ switch (motg->chg_type) {
+ case USB_DCP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ break;
+ case USB_CDP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ case USB_SDP_CHARGER:
+ msm_otg_notify_charger(motg, IUNIT);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ /*
+ * If charger detection work is pending, decrement
+ * the pm usage counter to balance with the one that
+ * is incremented in charger detection work.
+ */
+ if (cancel_delayed_work_sync(&motg->chg_work)) {
+ pm_runtime_put_sync(otg->dev);
+ msm_otg_reset(otg);
+ }
+ msm_otg_notify_charger(motg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
}
pm_runtime_put_sync(otg->dev);
break;
@@ -643,7 +1009,10 @@ static void msm_otg_sm_work(struct work_struct *w)
dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
if (!test_bit(B_SESS_VLD, &motg->inputs) ||
!test_bit(ID, &motg->inputs)) {
+ msm_otg_notify_charger(motg, 0);
msm_otg_start_peripheral(otg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
otg->state = OTG_STATE_B_IDLE;
msm_otg_reset(otg);
schedule_work(w);
@@ -935,6 +1304,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
writel(0, USB_OTGSC);
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+ INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
"msm_otg", motg);
if (ret) {
@@ -945,6 +1315,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
otg->init = msm_otg_reset;
otg->set_host = msm_otg_set_host;
otg->set_peripheral = msm_otg_set_peripheral;
+ otg->set_power = msm_otg_set_power;
otg->io_ops = &msm_otg_io_ops;
@@ -1003,6 +1374,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
return -EBUSY;
msm_otg_debugfs_cleanup();
+ cancel_delayed_work_sync(&motg->chg_work);
cancel_work_sync(&motg->sm_work);
pm_runtime_resume(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 31ef185..00311fe 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -54,6 +54,64 @@ enum otg_control_type {
};
/**
+ * PHY used in
+ *
+ * INVALID_PHY Unsupported PHY
+ * CI_45NM_INTEGRATED_PHY Chipidea 45nm integrated PHY
+ * SNPS_28NM_INTEGRATED_PHY Synopsis 28nm integrated PHY
+ *
+ */
+enum msm_usb_phy_type {
+ INVALID_PHY = 0,
+ CI_45NM_INTEGRATED_PHY,
+ SNPS_28NM_INTEGRATED_PHY,
+};
+
+#define IDEV_CHG_MAX 1500
+#define IUNIT 100
+
+/**
+ * Different states involved in USB charger detection.
+ *
+ * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
+ * process is not yet started.
+ * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
+ * USB_CHG_STATE_DCD_DONE Data pin contact is detected.
+ * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
+ * between SDP and DCP/CDP).
+ * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
+ * between DCP and CDP).
+ * USB_CHG_STATE_DETECTED USB charger type is determined.
+ *
+ */
+enum usb_chg_state {
+ USB_CHG_STATE_UNDEFINED = 0,
+ USB_CHG_STATE_WAIT_FOR_DCD,
+ USB_CHG_STATE_DCD_DONE,
+ USB_CHG_STATE_PRIMARY_DONE,
+ USB_CHG_STATE_SECONDARY_DONE,
+ USB_CHG_STATE_DETECTED,
+};
+
+/**
+ * USB charger types
+ *
+ * USB_INVALID_CHARGER Invalid USB charger.
+ * USB_SDP_CHARGER Standard downstream port. Refers to a downstream port
+ * on USB2.0 compliant host/hub.
+ * USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
+ * USB_CDP_CHARGER Charging downstream port. Enumeration can happen and
+ * IDEV_CHG_MAX can be drawn irrespective of USB state.
+ *
+ */
+enum usb_chg_type {
+ USB_INVALID_CHARGER = 0,
+ USB_SDP_CHARGER,
+ USB_DCP_CHARGER,
+ USB_CDP_CHARGER,
+};
+
+/**
* struct msm_otg_platform_data - platform device data
* for msm_otg driver.
* @phy_init_seq: PHY configuration sequence. val, reg pairs
@@ -74,6 +132,7 @@ struct msm_otg_platform_data {
enum usb_mode_type mode;
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
+ enum msm_usb_phy_type phy_type;
void (*setup_gpio)(enum usb_otg_state state);
char *pclk_src_name;
};
@@ -93,6 +152,12 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
+ * @cur_power: The amount of mA available from downstream port.
+ * @chg_work: Charger detection work.
+ * @chg_state: The state of charger detection process.
+ * @chg_type: The type of charger attached.
+ * @dcd_retires: The retry count used to track Data contact
+ * detection process.
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -110,6 +175,11 @@ struct msm_otg {
struct work_struct sm_work;
atomic_t in_lpm;
int async_int;
+ unsigned cur_power;
+ struct delayed_work chg_work;
+ enum usb_chg_state chg_state;
+ enum usb_chg_type chg_type;
+ u8 dcd_retries;
};
#endif
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V4 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains
2011-05-03 5:13 ` [PATCH V4 0/5] USB Charging, PHY init and " Pavankumar Kondeti
` (2 preceding siblings ...)
2011-05-03 5:13 ` [PATCH V4 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
@ 2011-05-03 5:13 ` Pavankumar Kondeti
2011-05-03 5:13 ` [PATCH V4 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
4 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-03 5:13 UTC (permalink / raw)
To: greg, linux-usb
Cc: linux-arm-msm, davidb, sshtylyov, Anji jonnala,
Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 189 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 189 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 526a650..a1233c5 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -38,6 +38,7 @@
#include <linux/usb/hcd.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
@@ -45,6 +46,171 @@
#define DRIVER_NAME "msm_otg"
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
+
+#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
+#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
+#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
+#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
+#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
+#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
+#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+
+static struct regulator *hsusb_3p3;
+static struct regulator *hsusb_1p8;
+static struct regulator *hsusb_vddcx;
+
+static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
+{
+ int ret = 0;
+
+ if (init) {
+ hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+ if (IS_ERR(hsusb_vddcx)) {
+ dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+ return PTR_ERR(hsusb_vddcx);
+ }
+
+ ret = regulator_set_voltage(hsusb_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage "
+ "for hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ return ret;
+ }
+
+ ret = regulator_enable(hsusb_vddcx);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ }
+ } else {
+ ret = regulator_set_voltage(hsusb_vddcx, 0,
+ USB_PHY_VDD_DIG_VOL_MIN);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage "
+ "for hsusb vddcx\n");
+ return ret;
+ }
+ ret = regulator_disable(hsusb_vddcx);
+ if (ret)
+ dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
+
+ regulator_put(hsusb_vddcx);
+ }
+
+ return ret;
+}
+
+static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
+{
+ int rc = 0;
+
+ if (init) {
+ hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
+ if (IS_ERR(hsusb_3p3)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
+ return PTR_ERR(hsusb_3p3);
+ }
+
+ rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
+ USB_PHY_3P3_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level "
+ "for hsusb 3p3\n");
+ goto put_3p3;
+ }
+ rc = regulator_enable(hsusb_3p3);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
+ goto put_3p3;
+ }
+ hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
+ if (IS_ERR(hsusb_1p8)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
+ rc = PTR_ERR(hsusb_1p8);
+ goto disable_3p3;
+ }
+ rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
+ USB_PHY_1P8_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level "
+ "for hsusb 1p8\n");
+ goto put_1p8;
+ }
+ rc = regulator_enable(hsusb_1p8);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
+ goto put_1p8;
+ }
+
+ return 0;
+ }
+
+ regulator_disable(hsusb_1p8);
+put_1p8:
+ regulator_put(hsusb_1p8);
+disable_3p3:
+ regulator_disable(hsusb_3p3);
+put_3p3:
+ regulator_put(hsusb_3p3);
+ return rc;
+}
+
+static int msm_hsusb_ldo_set_mode(int on)
+{
+ int ret = 0;
+
+ if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
+ pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
+ pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (on) {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator "
+ "HSUSB_1p8\n", __func__);
+ return ret;
+ }
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator "
+ "HSUSB_3p3\n", __func__);
+ regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ return ret;
+ }
+ } else {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator "
+ "HSUSB_1p8\n", __func__);
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator "
+ "HSUSB_3p3\n", __func__);
+ }
+
+ pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+ return ret < 0 ? ret : 0;
+}
+
static int ulpi_read(struct otg_transceiver *otg, u32 reg)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -1297,6 +1463,24 @@ static int __init msm_otg_probe(struct platform_device *pdev)
clk_enable(motg->clk);
clk_enable(motg->pclk);
+
+ ret = msm_hsusb_init_vddcx(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+ goto free_regs;
+ }
+
+ ret = msm_hsusb_ldo_init(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+ goto vddcx_exit;
+ }
+ ret = msm_hsusb_ldo_set_mode(1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+ goto ldo_exit;
+ }
+
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -1345,6 +1529,10 @@ free_irq:
disable_clks:
clk_disable(motg->pclk);
clk_disable(motg->clk);
+ldo_exit:
+ msm_hsusb_ldo_init(motg, 0);
+vddcx_exit:
+ msm_hsusb_init_vddcx(motg, 0);
free_regs:
iounmap(motg->regs);
put_core_clk:
@@ -1409,6 +1597,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->pclk_src);
clk_put(motg->pclk_src);
}
+ msm_hsusb_ldo_init(motg, 0);
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V4 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960
2011-05-03 5:13 ` [PATCH V4 0/5] USB Charging, PHY init and " Pavankumar Kondeti
` (3 preceding siblings ...)
2011-05-03 5:13 ` [PATCH V4 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
@ 2011-05-03 5:13 ` Pavankumar Kondeti
4 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-03 5:13 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, davidb, sshtylyov, Pavankumar Kondeti
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 64 ++++++++++++++++++++++++++++++++------
include/linux/usb/msm_hsusb_hw.h | 2 +
2 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index a1233c5..7d90252 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -163,6 +163,32 @@ put_3p3:
return rc;
}
+#ifdef CONFIG_PM_SLEEP
+#define USB_PHY_SUSP_DIG_VOL 500000
+static int msm_hsusb_config_vddcx(int high)
+{
+ int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+ int min_vol;
+ int ret;
+
+ if (high)
+ min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+ else
+ min_vol = USB_PHY_SUSP_DIG_VOL;
+
+ ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+ if (ret) {
+ pr_err("%s: unable to set the voltage for regulator "
+ "HSUSB_VDDCX\n", __func__);
+ return ret;
+ }
+
+ pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+ return ret;
+}
+#endif
+
static int msm_hsusb_ldo_set_mode(int on)
{
int ret = 0;
@@ -434,27 +460,28 @@ static int msm_otg_suspend(struct msm_otg *motg)
disable_irq(motg->irq);
/*
+ * Chipidea 45-nm PHY suspend sequence:
+ *
* Interrupt Latch Register auto-clear feature is not present
* in all PHY versions. Latch register is clear on read type.
* Clear latch register to avoid spurious wakeup from
* low power mode (LPM).
- */
- ulpi_read(otg, 0x14);
-
- /*
+ *
* PHY comparators are disabled when PHY enters into low power
* mode (LPM). Keep PHY comparators ON in LPM only when we expect
* VBUS/Id notifications from USB PHY. Otherwise turn off USB
* PHY comparators. This save significant amount of power.
- */
- if (pdata->otg_control == OTG_PHY_CONTROL)
- ulpi_write(otg, 0x01, 0x30);
-
- /*
+ *
* PLL is not turned off when PHY enters into low power mode (LPM).
* Disable PLL for maximum power savings.
*/
- ulpi_write(otg, 0x08, 0x09);
+
+ if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
+ ulpi_read(otg, 0x14);
+ if (pdata->otg_control == OTG_PHY_CONTROL)
+ ulpi_write(otg, 0x01, 0x30);
+ ulpi_write(otg, 0x08, 0x09);
+ }
/*
* PHY may take some time or even fail to enter into low power
@@ -485,6 +512,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
*/
writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL)
+ writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
+
clk_disable(motg->pclk);
clk_disable(motg->clk);
if (motg->core_clk)
@@ -493,6 +524,12 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (!IS_ERR(motg->pclk_src))
clk_disable(motg->pclk_src);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_set_mode(0);
+ msm_hsusb_config_vddcx(0);
+ }
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -524,6 +561,13 @@ static int msm_otg_resume(struct msm_otg *motg)
if (motg->core_clk)
clk_enable(motg->core_clk);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_set_mode(1);
+ msm_hsusb_config_vddcx(1);
+ writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
+ }
+
temp = readl(USB_USBCMD);
temp &= ~ASYNC_INTR_CTRL;
temp &= ~ULPI_STP_CTRL;
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 7d1babb..6e97a2d 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
#define USB_PORTSC (MSM_USB_BASE + 0x0184)
#define USB_OTGSC (MSM_USB_BASE + 0x01A4)
#define USB_USBMODE (MSM_USB_BASE + 0x01A8)
+#define USB_PHY_CTRL (MSM_USB_BASE + 0x0240)
#define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148)
@@ -42,6 +43,7 @@
#define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */
#define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */
+#define PHY_RETEN (1 << 1) /* PHY retention enable/disable */
/* OTG definitions */
#define OTGSC_INTSTS_MASK (0x7f << 16)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH V4 2/5] USB: OTG: msm: vote for dayatona fabric clock
[not found] ` <1304399633-16120-3-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-03 11:14 ` Sergei Shtylyov
2011-05-03 12:29 ` Pavan Kondeti
0 siblings, 1 reply; 45+ messages in thread
From: Sergei Shtylyov @ 2011-05-03 11:14 UTC (permalink / raw)
To: Pavankumar Kondeti
Cc: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
davidb-sgV2jX0FEOL9JmXXK+q4OQ, sshtylyov-Igf4POYTYCDQT0dZR+AlfA,
Anji jonnala
Hello.
On 03-05-2011 9:13, Pavankumar Kondeti wrote:
> From: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> HSUSB core clock is derived from daytona fabric clock and for
> HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
> cannot tolerate daytona fabric clock change in the middle of HSUSB
> operational, vote for maximum Daytona fabric clock
> while usb is operational
> Signed-off-by: Anji jonnala<anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Signed-off-by: Pavankumar Kondeti<pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
[...]
> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
> index 2965986..cfbb606 100644
> --- a/drivers/usb/otg/msm_otg.c
> +++ b/drivers/usb/otg/msm_otg.c
[...]
> @@ -954,7 +979,11 @@ free_regs:
> put_core_clk:
> if (motg->core_clk)
> clk_put(motg->core_clk);
> - clk_put(motg->pclk);
Is it really correct to remove this line?
> +put_pclk_src:
> + if (!IS_ERR(motg->pclk_src)) {
> + clk_disable(motg->pclk_src);
> + clk_put(motg->pclk_src);
> + }
> put_clk:
> clk_put(motg->clk);
> put_phy_reset_clk:
WBR, Sergei
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH V4 2/5] USB: OTG: msm: vote for dayatona fabric clock
2011-05-03 11:14 ` Sergei Shtylyov
@ 2011-05-03 12:29 ` Pavan Kondeti
2011-05-03 17:15 ` Greg KH
0 siblings, 1 reply; 45+ messages in thread
From: Pavan Kondeti @ 2011-05-03 12:29 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: greg, linux-usb, linux-arm-msm, davidb, Anji jonnala
Hi Sergei,
On 5/3/2011 4:44 PM, Sergei Shtylyov wrote:
> Hello.
>
> On 03-05-2011 9:13, Pavankumar Kondeti wrote:
>
>> From: Anji jonnala <anjir@codeaurora.org>
>
>> HSUSB core clock is derived from daytona fabric clock and for
>> HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
>> cannot tolerate daytona fabric clock change in the middle of HSUSB
>> operational, vote for maximum Daytona fabric clock
>> while usb is operational
>
>> Signed-off-by: Anji jonnala<anjir@codeaurora.org>
>> Signed-off-by: Pavankumar Kondeti<pkondeti@codeaurora.org>
> [...]
>
>> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
>> index 2965986..cfbb606 100644
>> --- a/drivers/usb/otg/msm_otg.c
>> +++ b/drivers/usb/otg/msm_otg.c
> [...]
>> @@ -954,7 +979,11 @@ free_regs:
>> put_core_clk:
>> if (motg->core_clk)
>> clk_put(motg->core_clk);
>> - clk_put(motg->pclk);
>
> Is it really correct to remove this line?
>
No. It is not correct. I will fix it in next version.
>> +put_pclk_src:
>> + if (!IS_ERR(motg->pclk_src)) {
>> + clk_disable(motg->pclk_src);
>> + clk_put(motg->pclk_src);
>> + }
>> put_clk:
>> clk_put(motg->clk);
>> put_phy_reset_clk:
>
> WBR, Sergei
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH V4 2/5] USB: OTG: msm: vote for dayatona fabric clock
2011-05-03 12:29 ` Pavan Kondeti
@ 2011-05-03 17:15 ` Greg KH
2011-05-04 4:48 ` Pavan Kondeti
0 siblings, 1 reply; 45+ messages in thread
From: Greg KH @ 2011-05-03 17:15 UTC (permalink / raw)
To: Pavan Kondeti
Cc: Sergei Shtylyov, linux-usb, linux-arm-msm, davidb, Anji jonnala
On Tue, May 03, 2011 at 05:59:37PM +0530, Pavan Kondeti wrote:
> Hi Sergei,
>
> On 5/3/2011 4:44 PM, Sergei Shtylyov wrote:
> > Hello.
> >
> > On 03-05-2011 9:13, Pavankumar Kondeti wrote:
> >
> >> From: Anji jonnala <anjir@codeaurora.org>
> >
> >> HSUSB core clock is derived from daytona fabric clock and for
> >> HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
> >> cannot tolerate daytona fabric clock change in the middle of HSUSB
> >> operational, vote for maximum Daytona fabric clock
> >> while usb is operational
> >
> >> Signed-off-by: Anji jonnala<anjir@codeaurora.org>
> >> Signed-off-by: Pavankumar Kondeti<pkondeti@codeaurora.org>
> > [...]
> >
> >> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
> >> index 2965986..cfbb606 100644
> >> --- a/drivers/usb/otg/msm_otg.c
> >> +++ b/drivers/usb/otg/msm_otg.c
> > [...]
> >> @@ -954,7 +979,11 @@ free_regs:
> >> put_core_clk:
> >> if (motg->core_clk)
> >> clk_put(motg->core_clk);
> >> - clk_put(motg->pclk);
> >
> > Is it really correct to remove this line?
> >
> No. It is not correct. I will fix it in next version.
Next version?
Ok, I'll drop all of these then from my queue. Please resend when you
have something working properly.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH V4 2/5] USB: OTG: msm: vote for dayatona fabric clock
2011-05-03 17:15 ` Greg KH
@ 2011-05-04 4:48 ` Pavan Kondeti
0 siblings, 0 replies; 45+ messages in thread
From: Pavan Kondeti @ 2011-05-04 4:48 UTC (permalink / raw)
To: Greg KH; +Cc: Sergei Shtylyov, linux-usb, linux-arm-msm, davidb, Anji jonnala
Hi Greg,
On 5/3/2011 10:45 PM, Greg KH wrote:
> On Tue, May 03, 2011 at 05:59:37PM +0530, Pavan Kondeti wrote:
>> Hi Sergei,
>>
>> On 5/3/2011 4:44 PM, Sergei Shtylyov wrote:
>>> Hello.
>>>
>>> On 03-05-2011 9:13, Pavankumar Kondeti wrote:
>>>
>>>> From: Anji jonnala <anjir@codeaurora.org>
>>>
>>>> HSUSB core clock is derived from daytona fabric clock and for
>>>> HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
>>>> cannot tolerate daytona fabric clock change in the middle of HSUSB
>>>> operational, vote for maximum Daytona fabric clock
>>>> while usb is operational
>>>
>>>> Signed-off-by: Anji jonnala<anjir@codeaurora.org>
>>>> Signed-off-by: Pavankumar Kondeti<pkondeti@codeaurora.org>
>>> [...]
>>>
>>>> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
>>>> index 2965986..cfbb606 100644
>>>> --- a/drivers/usb/otg/msm_otg.c
>>>> +++ b/drivers/usb/otg/msm_otg.c
>>> [...]
>>>> @@ -954,7 +979,11 @@ free_regs:
>>>> put_core_clk:
>>>> if (motg->core_clk)
>>>> clk_put(motg->core_clk);
>>>> - clk_put(motg->pclk);
>>>
>>> Is it really correct to remove this line?
>>>
>> No. It is not correct. I will fix it in next version.
>
> Next version?
>
I meant next patch set version. Again sorry for the confusion.
> Ok, I'll drop all of these then from my queue. Please resend when you
> have something working properly.
>
I have tested the patches well. The driver probe() never failed in my
testing. So could not found this BUG(). I am resending the patch series now.
Thanks,
Pavan
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH V5 0/4] USB Charging, PHY init and suspend support for MSM8960
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
` (8 preceding siblings ...)
2011-05-03 5:13 ` [PATCH V4 0/5] USB Charging, PHY init and " Pavankumar Kondeti
@ 2011-05-04 4:49 ` Pavankumar Kondeti
2011-05-04 4:49 ` [PATCH V5 1/4] USB: OTG: msm: vote for dayatona fabric clock Pavankumar Kondeti
` (2 more replies)
9 siblings, 3 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-04 4:49 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, davidb, sshtylyov, Pavankumar Kondeti
This patch series adds PHY based charging detection, PHY initialization and
suspend support for MSM8960 target.
Changelog
- V5
- Fixed error path in msm_otg probe
- V4
- Added missing spaces at the end of line for multi line printk messages.
- V3
- The third patch in this series unknowingly turning off pclk in resume. Fix
it.
- add "msm" in commit prefix for 2nd patch.
- V2
- logical AND operator is used instead of bitwiese AND for testing flags.
- Fixed error path and label names as per Sergei's comments.
- Fixed a typo mistake (s/phy_type/otg_control) pointed out by Sergei.
- Changed a never-changed-variable into a macro.
Anji jonnala (2):
USB: OTG: msm: vote for dayatona fabric clock
USB: OTG: msm: Configure PHY Analog and Digital voltage domains
Pavankumar Kondeti (2):
USB: OTG: msm: Implement charger detection
USB: OTG: msm: Add PHY suspend support for MSM8960
drivers/usb/gadget/ci13xxx_udc.c | 10 +
drivers/usb/otg/msm_otg.c | 669 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 79 +++++-
include/linux/usb/msm_hsusb_hw.h | 2 +
4 files changed, 742 insertions(+), 18 deletions(-)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH V5 1/4] USB: OTG: msm: vote for dayatona fabric clock
2011-05-04 4:49 ` [PATCH V5 0/4] USB Charging, PHY init and " Pavankumar Kondeti
@ 2011-05-04 4:49 ` Pavankumar Kondeti
2011-05-04 4:49 ` [PATCH V5 2/4] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
[not found] ` <1304484589-17186-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-04 4:49 UTC (permalink / raw)
To: greg, linux-usb
Cc: linux-arm-msm, davidb, sshtylyov, Anji jonnala,
Pavankumar Kondeti
From: Anji jonnala <anjir@codeaurora.org>
HSUSB core clock is derived from daytona fabric clock and for
HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
cannot tolerate daytona fabric clock change in the middle of HSUSB
operational, vote for maximum Daytona fabric clock
while usb is operational
Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/otg/msm_otg.c | 36 +++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 7 +++++--
2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index f58b7da..7792fef 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -324,6 +324,9 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src))
+ clk_disable(motg->pclk_src);
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -347,6 +350,9 @@ static int msm_otg_resume(struct msm_otg *motg)
if (!atomic_read(&motg->in_lpm))
return 0;
+ if (!IS_ERR(motg->pclk_src))
+ clk_enable(motg->pclk_src);
+
clk_enable(motg->pclk);
clk_enable(motg->clk);
if (motg->core_clk)
@@ -862,12 +868,31 @@ static int __init msm_otg_probe(struct platform_device *pdev)
ret = PTR_ERR(motg->clk);
goto put_phy_reset_clk;
}
+ clk_set_rate(motg->clk, 60000000);
+
+ /*
+ * If USB Core is running its protocol engine based on CORE CLK,
+ * CORE CLK must be running at >55Mhz for correct HSUSB
+ * operation and USB core cannot tolerate frequency changes on
+ * CORE CLK. For such USB cores, vote for maximum clk frequency
+ * on pclk source
+ */
+ if (motg->pdata->pclk_src_name) {
+ motg->pclk_src = clk_get(&pdev->dev,
+ motg->pdata->pclk_src_name);
+ if (IS_ERR(motg->pclk_src))
+ goto put_clk;
+ clk_set_rate(motg->pclk_src, INT_MAX);
+ clk_enable(motg->pclk_src);
+ } else
+ motg->pclk_src = ERR_PTR(-ENOENT);
+
motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
if (IS_ERR(motg->pclk)) {
dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
ret = PTR_ERR(motg->pclk);
- goto put_clk;
+ goto put_pclk_src;
}
/*
@@ -955,6 +980,11 @@ put_core_clk:
if (motg->core_clk)
clk_put(motg->core_clk);
clk_put(motg->pclk);
+put_pclk_src:
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
put_clk:
clk_put(motg->clk);
put_phy_reset_clk:
@@ -1004,6 +1034,10 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->clk);
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->pclk_src)) {
+ clk_disable(motg->pclk_src);
+ clk_put(motg->pclk_src);
+ }
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 3657403..31ef185 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -64,7 +64,8 @@ enum otg_control_type {
* @otg_control: OTG switch controlled by user/Id pin
* @default_mode: Default operational mode. Applicable only if
* OTG switch is controller by user.
- *
+ * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k
+ * dfab_usb_hs_clk in case of 8660 and 8960.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -74,6 +75,7 @@ struct msm_otg_platform_data {
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
void (*setup_gpio)(enum usb_otg_state state);
+ char *pclk_src_name;
};
/**
@@ -83,6 +85,7 @@ struct msm_otg_platform_data {
* @irq: IRQ number assigned for HSUSB controller.
* @clk: clock struct of usb_hs_clk.
* @pclk: clock struct of usb_hs_pclk.
+ * @pclk_src: pclk source for voting.
* @phy_reset_clk: clock struct of usb_phy_clk.
* @core_clk: clock struct of usb_hs_core_clk.
* @regs: ioremapped register base address.
@@ -90,7 +93,6 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
- *
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -98,6 +100,7 @@ struct msm_otg {
int irq;
struct clk *clk;
struct clk *pclk;
+ struct clk *pclk_src;
struct clk *phy_reset_clk;
struct clk *core_clk;
void __iomem *regs;
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V5 2/4] USB: OTG: msm: Implement charger detection
2011-05-04 4:49 ` [PATCH V5 0/4] USB Charging, PHY init and " Pavankumar Kondeti
2011-05-04 4:49 ` [PATCH V5 1/4] USB: OTG: msm: vote for dayatona fabric clock Pavankumar Kondeti
@ 2011-05-04 4:49 ` Pavankumar Kondeti
[not found] ` <1304484589-17186-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2 siblings, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-04 4:49 UTC (permalink / raw)
To: greg, linux-usb; +Cc: linux-arm-msm, davidb, sshtylyov, Pavankumar Kondeti
Implement good battery algorithm defined in the battery charging V1.2 spec
for detecting different charging ports. USB hardware is put into low power
mode when connected to a dedicated charging port. vbus_draw and set_power
methods are implemented for determining the allowed current from Host in
different states (un-configured/suspend/configured).
The charger block is implemented using vendor specific registers and the
PHY used in MSM8960(28nm PHY) different from older targets like MSM8x60
and MSM7x30(45nm PHY). The PHY vendor and product id registers are not
implemented in the above chipsets. Hence PHY type is passed via platform
data.
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
---
drivers/usb/gadget/ci13xxx_udc.c | 10 +
drivers/usb/otg/msm_otg.c | 380 +++++++++++++++++++++++++++++++++++++-
include/linux/usb/msm_hsusb.h | 72 +++++++-
3 files changed, 457 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 6f724bc..bf69bc3 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2517,6 +2517,15 @@ out:
return ret;
}
+static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+{
+ struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+
+ if (udc->transceiver)
+ return otg_set_power(udc->transceiver, mA);
+ return -ENOTSUPP;
+}
+
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
@@ -2525,6 +2534,7 @@ out:
static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci13xxx_vbus_session,
.wakeup = ci13xxx_wakeup,
+ .vbus_draw = ci13xxx_vbus_draw,
};
/**
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 7792fef..854b7e3 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -409,6 +409,33 @@ skip_phy_resume:
}
#endif
+static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
+{
+ if (motg->cur_power == mA)
+ return;
+
+ /* TODO: Notify PMIC about available current */
+ dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
+ motg->cur_power = mA;
+}
+
+static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+ struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+ /*
+ * Gadget driver uses set_power method to notify about the
+ * available current based on suspend/configured states.
+ *
+ * IDEV_CHG can be drawn irrespective of suspend/un-configured
+ * states when CDP/ACA is connected.
+ */
+ if (motg->chg_type == USB_SDP_CHARGER)
+ msm_otg_notify_charger(motg, mA);
+
+ return 0;
+}
+
static void msm_otg_start_host(struct otg_transceiver *otg, int on)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -563,6 +590,306 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg,
return 0;
}
+static bool msm_chg_check_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_secondary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* put it in host mode for enabling D- source */
+ chg_det &= ~(1 << 2);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DM as current source, DP as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x8, 0x85);
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ ret = chg_det & (1 << 4);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x87);
+ ret = chg_det & 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_enable_primary_det(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* enable chg detection */
+ chg_det &= ~(1 << 0);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /*
+ * Configure DP as current source, DM as current sink
+ * and enable battery charging comparators.
+ */
+ ulpi_write(otg, 0x2, 0x85);
+ ulpi_write(otg, 0x1, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool msm_chg_check_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 line_state;
+ bool ret = false;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x15);
+ ret = !(line_state & 1);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ line_state = ulpi_read(otg, 0x87);
+ ret = line_state & 2;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void msm_chg_disable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ chg_det &= ~(1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ ulpi_write(otg, 0x10, 0x86);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_enable_dcd(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn on D+ current source */
+ chg_det |= (1 << 5);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Data contact detection enable */
+ ulpi_write(otg, 0x10, 0x85);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_on(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ /* put the controller in non-driving mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* control chg block via ULPI */
+ chg_det &= ~(1 << 3);
+ ulpi_write(otg, chg_det, 0x34);
+ /* Turn on chg detect block */
+ chg_det &= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ udelay(20);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ udelay(100);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_block_off(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+ u32 func_ctrl, chg_det;
+
+ switch (motg->pdata->phy_type) {
+ case CI_45NM_INTEGRATED_PHY:
+ chg_det = ulpi_read(otg, 0x34);
+ /* Turn off charger block */
+ chg_det |= ~(1 << 1);
+ ulpi_write(otg, chg_det, 0x34);
+ break;
+ case SNPS_28NM_INTEGRATED_PHY:
+ /* Clear charger detecting control bits */
+ ulpi_write(otg, 0x3F, 0x86);
+ /* Clear alt interrupt latch and enable bits */
+ ulpi_write(otg, 0x1F, 0x92);
+ ulpi_write(otg, 0x1F, 0x95);
+ break;
+ default:
+ break;
+ }
+
+ /* put the controller in normal mode */
+ func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+ ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
+}
+
+#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
+#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
+static void msm_chg_detect_work(struct work_struct *w)
+{
+ struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
+ struct otg_transceiver *otg = &motg->otg;
+ bool is_dcd, tmout, vout;
+ unsigned long delay;
+
+ dev_dbg(otg->dev, "chg detection work\n");
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ pm_runtime_get_sync(otg->dev);
+ msm_chg_block_on(motg);
+ msm_chg_enable_dcd(motg);
+ motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
+ motg->dcd_retries = 0;
+ delay = MSM_CHG_DCD_POLL_TIME;
+ break;
+ case USB_CHG_STATE_WAIT_FOR_DCD:
+ is_dcd = msm_chg_check_dcd(motg);
+ tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
+ if (is_dcd || tmout) {
+ msm_chg_disable_dcd(motg);
+ msm_chg_enable_primary_det(motg);
+ delay = MSM_CHG_PRIMARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_DCD_DONE;
+ } else {
+ delay = MSM_CHG_DCD_POLL_TIME;
+ }
+ break;
+ case USB_CHG_STATE_DCD_DONE:
+ vout = msm_chg_check_primary_det(motg);
+ if (vout) {
+ msm_chg_enable_secondary_det(motg);
+ delay = MSM_CHG_SECONDARY_DET_TIME;
+ motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
+ } else {
+ motg->chg_type = USB_SDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ delay = 0;
+ }
+ break;
+ case USB_CHG_STATE_PRIMARY_DONE:
+ vout = msm_chg_check_secondary_det(motg);
+ if (vout)
+ motg->chg_type = USB_DCP_CHARGER;
+ else
+ motg->chg_type = USB_CDP_CHARGER;
+ motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
+ /* fall through */
+ case USB_CHG_STATE_SECONDARY_DONE:
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ case USB_CHG_STATE_DETECTED:
+ msm_chg_block_off(motg);
+ dev_dbg(otg->dev, "charger = %d\n", motg->chg_type);
+ schedule_work(&motg->sm_work);
+ return;
+ default:
+ return;
+ }
+
+ schedule_delayed_work(&motg->chg_work, delay);
+}
+
/*
* We support OTG, Peripheral only and Host only configurations. In case
* of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
@@ -633,9 +960,48 @@ static void msm_otg_sm_work(struct work_struct *w)
writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
msm_otg_start_host(otg, 1);
otg->state = OTG_STATE_A_HOST;
- } else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) {
- msm_otg_start_peripheral(otg, 1);
- otg->state = OTG_STATE_B_PERIPHERAL;
+ } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
+ switch (motg->chg_state) {
+ case USB_CHG_STATE_UNDEFINED:
+ msm_chg_detect_work(&motg->chg_work.work);
+ break;
+ case USB_CHG_STATE_DETECTED:
+ switch (motg->chg_type) {
+ case USB_DCP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ break;
+ case USB_CDP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ case USB_SDP_CHARGER:
+ msm_otg_notify_charger(motg, IUNIT);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ /*
+ * If charger detection work is pending, decrement
+ * the pm usage counter to balance with the one that
+ * is incremented in charger detection work.
+ */
+ if (cancel_delayed_work_sync(&motg->chg_work)) {
+ pm_runtime_put_sync(otg->dev);
+ msm_otg_reset(otg);
+ }
+ msm_otg_notify_charger(motg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
}
pm_runtime_put_sync(otg->dev);
break;
@@ -643,7 +1009,10 @@ static void msm_otg_sm_work(struct work_struct *w)
dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
if (!test_bit(B_SESS_VLD, &motg->inputs) ||
!test_bit(ID, &motg->inputs)) {
+ msm_otg_notify_charger(motg, 0);
msm_otg_start_peripheral(otg, 0);
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ motg->chg_type = USB_INVALID_CHARGER;
otg->state = OTG_STATE_B_IDLE;
msm_otg_reset(otg);
schedule_work(w);
@@ -935,6 +1304,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
writel(0, USB_OTGSC);
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+ INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
"msm_otg", motg);
if (ret) {
@@ -945,6 +1315,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
otg->init = msm_otg_reset;
otg->set_host = msm_otg_set_host;
otg->set_peripheral = msm_otg_set_peripheral;
+ otg->set_power = msm_otg_set_power;
otg->io_ops = &msm_otg_io_ops;
@@ -1004,6 +1375,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
return -EBUSY;
msm_otg_debugfs_cleanup();
+ cancel_delayed_work_sync(&motg->chg_work);
cancel_work_sync(&motg->sm_work);
pm_runtime_resume(&pdev->dev);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 31ef185..00311fe 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -54,6 +54,64 @@ enum otg_control_type {
};
/**
+ * PHY used in
+ *
+ * INVALID_PHY Unsupported PHY
+ * CI_45NM_INTEGRATED_PHY Chipidea 45nm integrated PHY
+ * SNPS_28NM_INTEGRATED_PHY Synopsis 28nm integrated PHY
+ *
+ */
+enum msm_usb_phy_type {
+ INVALID_PHY = 0,
+ CI_45NM_INTEGRATED_PHY,
+ SNPS_28NM_INTEGRATED_PHY,
+};
+
+#define IDEV_CHG_MAX 1500
+#define IUNIT 100
+
+/**
+ * Different states involved in USB charger detection.
+ *
+ * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
+ * process is not yet started.
+ * USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
+ * USB_CHG_STATE_DCD_DONE Data pin contact is detected.
+ * USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
+ * between SDP and DCP/CDP).
+ * USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
+ * between DCP and CDP).
+ * USB_CHG_STATE_DETECTED USB charger type is determined.
+ *
+ */
+enum usb_chg_state {
+ USB_CHG_STATE_UNDEFINED = 0,
+ USB_CHG_STATE_WAIT_FOR_DCD,
+ USB_CHG_STATE_DCD_DONE,
+ USB_CHG_STATE_PRIMARY_DONE,
+ USB_CHG_STATE_SECONDARY_DONE,
+ USB_CHG_STATE_DETECTED,
+};
+
+/**
+ * USB charger types
+ *
+ * USB_INVALID_CHARGER Invalid USB charger.
+ * USB_SDP_CHARGER Standard downstream port. Refers to a downstream port
+ * on USB2.0 compliant host/hub.
+ * USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
+ * USB_CDP_CHARGER Charging downstream port. Enumeration can happen and
+ * IDEV_CHG_MAX can be drawn irrespective of USB state.
+ *
+ */
+enum usb_chg_type {
+ USB_INVALID_CHARGER = 0,
+ USB_SDP_CHARGER,
+ USB_DCP_CHARGER,
+ USB_CDP_CHARGER,
+};
+
+/**
* struct msm_otg_platform_data - platform device data
* for msm_otg driver.
* @phy_init_seq: PHY configuration sequence. val, reg pairs
@@ -74,6 +132,7 @@ struct msm_otg_platform_data {
enum usb_mode_type mode;
enum otg_control_type otg_control;
enum usb_mode_type default_mode;
+ enum msm_usb_phy_type phy_type;
void (*setup_gpio)(enum usb_otg_state state);
char *pclk_src_name;
};
@@ -93,6 +152,12 @@ struct msm_otg_platform_data {
* @sm_work: OTG state machine work.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: Async interrupt arrived.
+ * @cur_power: The amount of mA available from downstream port.
+ * @chg_work: Charger detection work.
+ * @chg_state: The state of charger detection process.
+ * @chg_type: The type of charger attached.
+ * @dcd_retires: The retry count used to track Data contact
+ * detection process.
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -110,6 +175,11 @@ struct msm_otg {
struct work_struct sm_work;
atomic_t in_lpm;
int async_int;
+ unsigned cur_power;
+ struct delayed_work chg_work;
+ enum usb_chg_state chg_state;
+ enum usb_chg_type chg_type;
+ u8 dcd_retries;
};
#endif
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V5 3/4] USB: OTG: msm: Configure PHY Analog and Digital voltage domains
[not found] ` <1304484589-17186-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2011-05-04 4:49 ` Pavankumar Kondeti
2011-05-04 4:49 ` [PATCH V5 4/4] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
1 sibling, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-04 4:49 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
davidb-sgV2jX0FEOL9JmXXK+q4OQ, sshtylyov-Igf4POYTYCDQT0dZR+AlfA,
Anji jonnala, Pavankumar Kondeti
From: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Anji jonnala <anjir-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Signed-off-by: Pavankumar Kondeti <pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/usb/otg/msm_otg.c | 189 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 189 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 854b7e3..628ba7d 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -38,6 +38,7 @@
#include <linux/usb/hcd.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
@@ -45,6 +46,171 @@
#define DRIVER_NAME "msm_otg"
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
+
+#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
+#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
+#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
+#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
+#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
+#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
+#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
+
+#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+
+static struct regulator *hsusb_3p3;
+static struct regulator *hsusb_1p8;
+static struct regulator *hsusb_vddcx;
+
+static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
+{
+ int ret = 0;
+
+ if (init) {
+ hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
+ if (IS_ERR(hsusb_vddcx)) {
+ dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
+ return PTR_ERR(hsusb_vddcx);
+ }
+
+ ret = regulator_set_voltage(hsusb_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage "
+ "for hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ return ret;
+ }
+
+ ret = regulator_enable(hsusb_vddcx);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n");
+ regulator_put(hsusb_vddcx);
+ }
+ } else {
+ ret = regulator_set_voltage(hsusb_vddcx, 0,
+ USB_PHY_VDD_DIG_VOL_MIN);
+ if (ret) {
+ dev_err(motg->otg.dev, "unable to set the voltage "
+ "for hsusb vddcx\n");
+ return ret;
+ }
+ ret = regulator_disable(hsusb_vddcx);
+ if (ret)
+ dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
+
+ regulator_put(hsusb_vddcx);
+ }
+
+ return ret;
+}
+
+static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
+{
+ int rc = 0;
+
+ if (init) {
+ hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
+ if (IS_ERR(hsusb_3p3)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
+ return PTR_ERR(hsusb_3p3);
+ }
+
+ rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
+ USB_PHY_3P3_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level "
+ "for hsusb 3p3\n");
+ goto put_3p3;
+ }
+ rc = regulator_enable(hsusb_3p3);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n");
+ goto put_3p3;
+ }
+ hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
+ if (IS_ERR(hsusb_1p8)) {
+ dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
+ rc = PTR_ERR(hsusb_1p8);
+ goto disable_3p3;
+ }
+ rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
+ USB_PHY_1P8_VOL_MAX);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to set voltage level "
+ "for hsusb 1p8\n");
+ goto put_1p8;
+ }
+ rc = regulator_enable(hsusb_1p8);
+ if (rc) {
+ dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n");
+ goto put_1p8;
+ }
+
+ return 0;
+ }
+
+ regulator_disable(hsusb_1p8);
+put_1p8:
+ regulator_put(hsusb_1p8);
+disable_3p3:
+ regulator_disable(hsusb_3p3);
+put_3p3:
+ regulator_put(hsusb_3p3);
+ return rc;
+}
+
+static int msm_hsusb_ldo_set_mode(int on)
+{
+ int ret = 0;
+
+ if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
+ pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
+ pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
+ return -ENODEV;
+ }
+
+ if (on) {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator "
+ "HSUSB_1p8\n", __func__);
+ return ret;
+ }
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator "
+ "HSUSB_3p3\n", __func__);
+ regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ return ret;
+ }
+ } else {
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator "
+ "HSUSB_1p8\n", __func__);
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_LPM_LOAD);
+ if (ret < 0)
+ pr_err("%s: Unable to set LPM of the regulator "
+ "HSUSB_3p3\n", __func__);
+ }
+
+ pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+ return ret < 0 ? ret : 0;
+}
+
static int ulpi_read(struct otg_transceiver *otg, u32 reg)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
@@ -1297,6 +1463,24 @@ static int __init msm_otg_probe(struct platform_device *pdev)
clk_enable(motg->clk);
clk_enable(motg->pclk);
+
+ ret = msm_hsusb_init_vddcx(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+ goto free_regs;
+ }
+
+ ret = msm_hsusb_ldo_init(motg, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+ goto vddcx_exit;
+ }
+ ret = msm_hsusb_ldo_set_mode(1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+ goto ldo_exit;
+ }
+
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -1345,6 +1529,10 @@ free_irq:
disable_clks:
clk_disable(motg->pclk);
clk_disable(motg->clk);
+ldo_exit:
+ msm_hsusb_ldo_init(motg, 0);
+vddcx_exit:
+ msm_hsusb_init_vddcx(motg, 0);
free_regs:
iounmap(motg->regs);
put_core_clk:
@@ -1410,6 +1598,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
clk_disable(motg->pclk_src);
clk_put(motg->pclk_src);
}
+ msm_hsusb_ldo_init(motg, 0);
iounmap(motg->regs);
pm_runtime_set_suspended(&pdev->dev);
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH V5 4/4] USB: OTG: msm: Add PHY suspend support for MSM8960
[not found] ` <1304484589-17186-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-04 4:49 ` [PATCH V5 3/4] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
@ 2011-05-04 4:49 ` Pavankumar Kondeti
1 sibling, 0 replies; 45+ messages in thread
From: Pavankumar Kondeti @ 2011-05-04 4:49 UTC (permalink / raw)
To: greg-U8xfFu+wG4EAvxtiuMwx3w, linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
davidb-sgV2jX0FEOL9JmXXK+q4OQ, sshtylyov-Igf4POYTYCDQT0dZR+AlfA,
Pavankumar Kondeti
Signed-off-by: Pavankumar Kondeti <pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
---
drivers/usb/otg/msm_otg.c | 64 ++++++++++++++++++++++++++++++++------
include/linux/usb/msm_hsusb_hw.h | 2 +
2 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 628ba7d..1cdda6c 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -163,6 +163,32 @@ put_3p3:
return rc;
}
+#ifdef CONFIG_PM_SLEEP
+#define USB_PHY_SUSP_DIG_VOL 500000
+static int msm_hsusb_config_vddcx(int high)
+{
+ int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+ int min_vol;
+ int ret;
+
+ if (high)
+ min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+ else
+ min_vol = USB_PHY_SUSP_DIG_VOL;
+
+ ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+ if (ret) {
+ pr_err("%s: unable to set the voltage for regulator "
+ "HSUSB_VDDCX\n", __func__);
+ return ret;
+ }
+
+ pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+ return ret;
+}
+#endif
+
static int msm_hsusb_ldo_set_mode(int on)
{
int ret = 0;
@@ -434,27 +460,28 @@ static int msm_otg_suspend(struct msm_otg *motg)
disable_irq(motg->irq);
/*
+ * Chipidea 45-nm PHY suspend sequence:
+ *
* Interrupt Latch Register auto-clear feature is not present
* in all PHY versions. Latch register is clear on read type.
* Clear latch register to avoid spurious wakeup from
* low power mode (LPM).
- */
- ulpi_read(otg, 0x14);
-
- /*
+ *
* PHY comparators are disabled when PHY enters into low power
* mode (LPM). Keep PHY comparators ON in LPM only when we expect
* VBUS/Id notifications from USB PHY. Otherwise turn off USB
* PHY comparators. This save significant amount of power.
- */
- if (pdata->otg_control == OTG_PHY_CONTROL)
- ulpi_write(otg, 0x01, 0x30);
-
- /*
+ *
* PLL is not turned off when PHY enters into low power mode (LPM).
* Disable PLL for maximum power savings.
*/
- ulpi_write(otg, 0x08, 0x09);
+
+ if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
+ ulpi_read(otg, 0x14);
+ if (pdata->otg_control == OTG_PHY_CONTROL)
+ ulpi_write(otg, 0x01, 0x30);
+ ulpi_write(otg, 0x08, 0x09);
+ }
/*
* PHY may take some time or even fail to enter into low power
@@ -485,6 +512,10 @@ static int msm_otg_suspend(struct msm_otg *motg)
*/
writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL)
+ writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
+
clk_disable(motg->pclk);
clk_disable(motg->clk);
if (motg->core_clk)
@@ -493,6 +524,12 @@ static int msm_otg_suspend(struct msm_otg *motg)
if (!IS_ERR(motg->pclk_src))
clk_disable(motg->pclk_src);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_set_mode(0);
+ msm_hsusb_config_vddcx(0);
+ }
+
if (device_may_wakeup(otg->dev))
enable_irq_wake(motg->irq);
if (bus)
@@ -524,6 +561,13 @@ static int msm_otg_resume(struct msm_otg *motg)
if (motg->core_clk)
clk_enable(motg->core_clk);
+ if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
+ motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+ msm_hsusb_ldo_set_mode(1);
+ msm_hsusb_config_vddcx(1);
+ writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
+ }
+
temp = readl(USB_USBCMD);
temp &= ~ASYNC_INTR_CTRL;
temp &= ~ULPI_STP_CTRL;
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 7d1babb..6e97a2d 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -24,6 +24,7 @@
#define USB_PORTSC (MSM_USB_BASE + 0x0184)
#define USB_OTGSC (MSM_USB_BASE + 0x01A4)
#define USB_USBMODE (MSM_USB_BASE + 0x01A8)
+#define USB_PHY_CTRL (MSM_USB_BASE + 0x0240)
#define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148)
@@ -42,6 +43,7 @@
#define ASYNC_INTR_CTRL (1 << 29) /* Enable async interrupt */
#define ULPI_STP_CTRL (1 << 30) /* Block communication with PHY */
+#define PHY_RETEN (1 << 1) /* PHY retention enable/disable */
/* OTG definitions */
#define OTGSC_INTSTS_MASK (0x7f << 16)
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 45+ messages in thread
end of thread, other threads:[~2011-05-04 4:50 UTC | newest]
Thread overview: 45+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-28 8:01 [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
2011-04-28 8:01 ` [PATCH 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
2011-04-28 8:01 ` [PATCH 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
2011-04-28 8:01 ` [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
2011-04-29 10:14 ` Sergei Shtylyov
2011-05-02 6:03 ` Pavan Kondeti
2011-04-28 8:01 ` [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
2011-04-28 14:49 ` Sergei Shtylyov
2011-04-29 5:20 ` Pavan Kondeti
2011-04-28 12:18 ` [PATCH 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Sergei Shtylyov
2011-04-29 5:16 ` Pavan Kondeti
2011-04-29 5:22 ` Pavankumar Kondeti
2011-04-29 5:22 ` [PATCH 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
2011-04-29 5:22 ` [PATCH 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
[not found] ` <1304054532-3523-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-04-29 5:22 ` [PATCH 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
2011-04-29 5:22 ` [PATCH 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 0/5] USB Charging, PHY init and " Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 2/5] USB: OTG: vote for dayatona fabric clock Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
[not found] ` <1304318192-24374-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-02 6:36 ` [PATCH V2 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
2011-05-02 6:36 ` [PATCH V2 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
2011-05-02 12:22 ` Sergei Shtylyov
2011-05-03 5:01 ` Pavan Kondeti
[not found] ` <1303977693-18389-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-02 9:58 ` [PATCH V3 0/5] USB Charging, PHY init and " Pavankumar Kondeti
[not found] ` <1304330325-21982-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-02 9:58 ` [PATCH V3 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
2011-05-02 9:58 ` [PATCH V3 2/5] USB: OTG: msm: vote for dayatona fabric clock Pavankumar Kondeti
2011-05-02 9:58 ` [PATCH V3 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
2011-05-02 9:58 ` [PATCH V3 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
2011-05-02 9:58 ` [PATCH V3 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
2011-05-03 5:13 ` [PATCH V4 0/5] USB Charging, PHY init and " Pavankumar Kondeti
[not found] ` <1304399633-16120-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-03 5:13 ` [PATCH V4 1/5] USB: gadget: Use Zero Interrupt Threshold Control for ci13xxx_msm Pavankumar Kondeti
2011-05-03 5:13 ` [PATCH V4 2/5] USB: OTG: msm: vote for dayatona fabric clock Pavankumar Kondeti
[not found] ` <1304399633-16120-3-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-03 11:14 ` Sergei Shtylyov
2011-05-03 12:29 ` Pavan Kondeti
2011-05-03 17:15 ` Greg KH
2011-05-04 4:48 ` Pavan Kondeti
2011-05-03 5:13 ` [PATCH V4 3/5] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
2011-05-03 5:13 ` [PATCH V4 4/5] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
2011-05-03 5:13 ` [PATCH V4 5/5] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
2011-05-04 4:49 ` [PATCH V5 0/4] USB Charging, PHY init and " Pavankumar Kondeti
2011-05-04 4:49 ` [PATCH V5 1/4] USB: OTG: msm: vote for dayatona fabric clock Pavankumar Kondeti
2011-05-04 4:49 ` [PATCH V5 2/4] USB: OTG: msm: Implement charger detection Pavankumar Kondeti
[not found] ` <1304484589-17186-1-git-send-email-pkondeti-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2011-05-04 4:49 ` [PATCH V5 3/4] USB: OTG: msm: Configure PHY Analog and Digital voltage domains Pavankumar Kondeti
2011-05-04 4:49 ` [PATCH V5 4/4] USB: OTG: msm: Add PHY suspend support for MSM8960 Pavankumar Kondeti
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).