]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
usb: gadget: tegra:fix delay in charging icon in UI
authorPhilip Rakity <prakity@nvidia.com>
Wed, 26 Mar 2014 06:10:25 +0000 (11:40 +0530)
committerRiham Haidar <rhaidar@nvidia.com>
Mon, 28 Apr 2014 22:20:52 +0000 (15:20 -0700)
Moving CDP charger detection to early phase and
also setting charger current to Non-standard
before QC2.0 charger detection to fix delay in
charging icon in UI.

Bug 1424733
Bug 1458999

(cherry picked from commit 4f0e5756869074d27d808eab2225459c6daec5fb)
(cherry picked from commit 57b2e6af46175c3f8992bc29e7ec1a778f9002f1)
Change-Id: I0db19bf633b0d76d687d64e5599ccf41ef469876
Reviewed-on: http://git-master/r/384598
Reviewed-on: http://git-master/r/396042
Signed-off-by: Rakesh Bodla <rbodla@nvidia.com>
Signed-off-by: Philip Rakity <prakity@nvidia.com>
Reviewed-on: http://git-master/r/401889
Reviewed-by: Riham Haidar <rhaidar@nvidia.com>
Tested-by: Riham Haidar <rhaidar@nvidia.com>
drivers/usb/gadget/tegra_udc.c
drivers/usb/gadget/tegra_udc.h

index 7d1c0e6b5305f7cd05672c2d47e71d504758d97e..2f40ea5afdf60086382c2a91ecdb292eee824b39 100644 (file)
@@ -1482,51 +1482,6 @@ static int tegra_usb_set_charging_current(struct tegra_udc *udc)
        return ret;
 }
 
-static void tegra_detect_charging_type_is_cdp_or_dcp(struct tegra_udc *udc)
-{
-       u32 portsc;
-       u32 temp;
-       unsigned long flags;
-
-       /* use spinlock to prevent kernel preemption here */
-       spin_lock_irqsave(&udc->lock, flags);
-       if (udc->support_pmu_vbus) {
-                       temp = udc_readl(udc, VBUS_SENSOR_REG_OFFSET);
-                       temp |= (USB_SYS_VBUS_A_VLD_SW_VALUE |
-                                       USB_SYS_VBUS_A_VLD_SW_EN |
-                                       USB_SYS_VBUS_ASESSION_VLD_SW_VALUE |
-                                       USB_SYS_VBUS_ASESSION_VLD_SW_EN);
-                       udc_writel(udc, temp, VBUS_SENSOR_REG_OFFSET);
-       }
-
-       /* set controller to run which cause D+ pull high */
-       temp = udc_readl(udc, USB_CMD_REG_OFFSET);
-       temp |= USB_CMD_RUN_STOP;
-       udc_writel(udc, temp, USB_CMD_REG_OFFSET);
-
-       udelay(10);
-
-       /* use D+ and D- status to check it is CDP or DCP */
-       portsc = udc_readl(udc, PORTSCX_REG_OFFSET);
-       portsc &= PORTSCX_LINE_STATUS_BITS;
-       if (portsc == PORTSCX_LINE_STATUS_BITS)
-               tegra_udc_set_charger_type(udc, CONNECT_TYPE_DCP);
-       else if (portsc == PORTSCX_LINE_STATUS_DP_BIT)
-               tegra_udc_set_charger_type(udc, CONNECT_TYPE_CDP);
-       else
-               /*
-                * If it take more 100mS between D+ pull high and read
-                * Line Status, host might initiate the RESET, then we
-                * see both  line status as 0 (SE0). This really should
-                * not happen as we disabled the kernel preemption
-                * before reaching here.
-                * Bug can be raised here but it is also safe to assume
-                * as CDP.
-                */
-               tegra_udc_set_charger_type(udc, CONNECT_TYPE_CDP);
-       spin_unlock_irqrestore(&udc->lock, flags);
-}
-
 static int tegra_detect_cable_type(struct tegra_udc *udc)
 {
        if (!udc->charging_supported) {
@@ -1535,11 +1490,29 @@ static int tegra_detect_cable_type(struct tegra_udc *udc)
        }
 
        if (tegra_usb_phy_charger_detected(udc->phy)) {
-               if (tegra_usb_phy_qc2_charger_detected(udc->phy,
-                               udc->qc2_voltage))
-                       tegra_udc_set_charger_type(udc, CONNECT_TYPE_DCP_QC2);
-               else
-                       tegra_detect_charging_type_is_cdp_or_dcp(udc);
+               if (tegra_usb_phy_cdp_charger_detected(udc->phy))
+                       tegra_udc_set_charger_type(udc, CONNECT_TYPE_CDP);
+               else if (udc->qc2_voltage) {
+                       /* Must be DCP -- figure out if Quick Charge 2 or DCP.
+                        * Initially set low current since QC2 will reset to
+                        * 5V if current is too high when it changes to higher
+                        * voltage during detection. So setting to non-standard
+                        * which sets for low current. Also, setting current
+                        * early allows the charging icon to show up on UI.
+                        */
+                       tegra_udc_set_charger_type(udc,
+                                       CONNECT_TYPE_NON_STANDARD_CHARGER);
+                       tegra_usb_set_charging_current(udc);
+
+                        if (tegra_usb_phy_qc2_charger_detected(udc->phy,
+                                       udc->qc2_voltage))
+                               tegra_udc_set_charger_type(udc,
+                                       CONNECT_TYPE_DCP_QC2);
+                       else
+                               tegra_udc_set_charger_type(udc,
+                                       CONNECT_TYPE_DCP);
+               } else
+                       tegra_udc_set_charger_type(udc, CONNECT_TYPE_DCP);
        }
 #if !defined(CONFIG_ARCH_TEGRA_11x_SOC) && !defined(CONFIG_ARCH_TEGRA_14x_SOC)
        else if (tegra_usb_phy_apple_500ma_charger_detected(udc->phy))
@@ -2874,6 +2847,15 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
                        udc->fence_read = true;
 
                udc->charging_supported = pdata->u_data.dev.charging_supported;
+               udc->qc2_voltage = pdata->qc2_voltage;
+
+               udc->qc2_current_limit =
+                       pdata->u_data.dev.qc2_current_limit_ma * 1000;
+
+               DBG("%s: QC2 voltage = %d, current = %d\n",
+                       __func__,
+                       udc->qc2_voltage_limit,
+                       udc->qc2_current_limit);
 
                if (pdata->u_data.dev.dcp_current_limit_ma)
                        udc->dcp_current_limit =
@@ -2881,13 +2863,6 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
                else
                        udc->dcp_current_limit =
                                USB_CHARGING_DCP_CURRENT_LIMIT_UA;
-
-               if (pdata->u_data.dev.qc2_current_limit_ma)
-                       udc->qc2_current_limit =
-                               pdata->u_data.dev.qc2_current_limit_ma * 1000;
-               else
-                       udc->qc2_current_limit =
-                               USB_CHARGING_DCP_CURRENT_LIMIT_UA;
        } else {
                dev_err(&pdev->dev, "failed to get platform_data\n");
                err = -ENODATA;
@@ -3008,11 +2983,6 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
                        "usb_bat_chg regulator not registered:"
                                " USB charging will not be enabled\n");
                udc->vbus_reg = NULL;
-       } else {
-               udc->qc2_voltage = pdata->qc2_voltage;
-               DBG("%s: qc2_v(i) = %d, qc2_v(o) = %d\n",
-                       __func__,
-                       pdata->qc2_voltage, udc->qc2_voltage);
        }
 
        if (pdata->port_otg)
index 9f437dac9608b4ccf42deea2701b443833606ce0..44d0a08fa8e253059a9056d9a17736f046650935 100644 (file)
@@ -451,6 +451,7 @@ struct tegra_udc {
        enum tegra_connect_type connect_type;
        enum tegra_connect_type prev_connect_type;
        enum tegra_connect_type connect_type_lp0;
+       enum tegra_usb_qc2_voltage qc2_voltage;
        void __iomem *regs;
        size_t ep_qh_size;              /* size after alignment adjustment*/
        dma_addr_t ep_qh_dma;           /* dma address of QH */
@@ -477,7 +478,6 @@ struct tegra_udc {
        bool fence_read;
        bool vbus_in_lp0;
        bool charging_supported;
-       enum tegra_usb_qc2_voltage qc2_voltage;
 #ifdef CONFIG_EXTCON
        struct extcon_dev *edev;
        struct extcon_dev *vbus_extcon_dev;