From patchwork Thu Sep 27 20:08:39 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mathieu Poirier X-Patchwork-Id: 11795 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id A08B724140 for ; Thu, 27 Sep 2012 20:09:49 +0000 (UTC) Received: from mail-ie0-f180.google.com (mail-ie0-f180.google.com [209.85.223.180]) by fiordland.canonical.com (Postfix) with ESMTP id 4DDB4A18B18 for ; Thu, 27 Sep 2012 20:09:49 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id e10so5234801iej.11 for ; Thu, 27 Sep 2012 13:09:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to :subject:date:message-id:x-mailer:in-reply-to:references :mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=BasNPbFme6rO/0iKHe171eWhr1S38yqC9Ts/pg3wLjk=; b=JMOpq6iX7jlvRbVLzPO3HjXqqzTa85IIumAdTFFZ6B0lPfnJCdJYeBaa63zXLFlSXP uSSGsVkcn4KwW+1z++njqdLUnXpg1NjBlO9ttLHHO29FDcWwRZCsauKVufVc7NpVXBhn TEnAvB8mV2Zh1OYc26VnvpKzaZvOy5rQ4cUJkFJIglFIvhkDrJw9wjrkvPVoS9rcU7qa YRI8fPXTAopG7w+7g64YOYbDUc0Hfj1f+FawXfaWP6yXgbSQ6Wse/01OuHxBILRBzKBJ qr4HZOd5c+ZKtYbXAhM3dQ3qb5NSR7IAIckX3mvzzJmo2Etlwfb4meaGBK6X2cgxXn5C wuuA== Received: by 10.50.195.134 with SMTP id ie6mr4709674igc.28.1348776589037; Thu, 27 Sep 2012 13:09:49 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.184.232 with SMTP id ex8csp436310igc; Thu, 27 Sep 2012 13:09:48 -0700 (PDT) Received: by 10.68.132.41 with SMTP id or9mr14766136pbb.67.1348776588259; Thu, 27 Sep 2012 13:09:48 -0700 (PDT) Received: from mail-pb0-f50.google.com (mail-pb0-f50.google.com [209.85.160.50]) by mx.google.com with ESMTPS id pi9si5467641pbb.12.2012.09.27.13.09.48 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 27 Sep 2012 13:09:48 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of mathieu.poirier@linaro.org) client-ip=209.85.160.50; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of mathieu.poirier@linaro.org) smtp.mail=mathieu.poirier@linaro.org Received: by mail-pb0-f50.google.com with SMTP id md4so1686045pbc.37 for ; Thu, 27 Sep 2012 13:09:48 -0700 (PDT) Received: by 10.68.221.72 with SMTP id qc8mr14560118pbc.63.1348776588027; Thu, 27 Sep 2012 13:09:48 -0700 (PDT) Received: from localhost.localdomain (S0106002369de4dac.cg.shawcable.net. [70.73.24.112]) by mx.google.com with ESMTPS id sa2sm1587890pbc.4.2012.09.27.13.09.46 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 27 Sep 2012 13:09:47 -0700 (PDT) From: mathieu.poirier@linaro.org To: patches@linaro.org Subject: [PATCH 22/57] power: AB workaround for invalid charger Date: Thu, 27 Sep 2012 14:08:39 -0600 Message-Id: <1348776554-10019-23-git-send-email-mathieu.poirier@linaro.org> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1348776554-10019-1-git-send-email-mathieu.poirier@linaro.org> References: <1348776554-10019-1-git-send-email-mathieu.poirier@linaro.org> MIME-Version: 1.0 X-Gm-Message-State: ALoCoQlxt/fy4oREKHLRAZXId2sfb++pyROZCv+DDUtRniDIQt6Gjhb0xbvcplxAEfBhItvbvTU1 From: Henrik Sölver AB8500 refuses to start charging when some types of non standard chargers are connected. This change force the AB to start charging. Signed-off-by: Henrik Sölver Signed-off-by: Mathieu Poirier Reviewed-by: Yvan FILLION Reviewed-by: Jonas ABERG --- drivers/power/ab8500_charger.c | 70 +++++++++++++++++++++++++++++++++++++-- 1 files changed, 66 insertions(+), 4 deletions(-) diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 7cd4165..cbc9fd7 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -203,6 +203,7 @@ struct ab8500_charger_usb_state { * @old_vbat Previously measured battery voltage * @usb_device_is_unrecognised USB device is unrecognised by the hardware * @autopower Indicate if we should have automatic pwron after pwrloss + * @invalid_charger_detect_state State when forcing AB to use invalid charger * @parent: Pointer to the struct ab8500 * @gpadc: Pointer to the struct gpadc * @pdata: Pointer to the abx500_charger platform data @@ -246,6 +247,7 @@ struct ab8500_charger { int old_vbat; bool usb_device_is_unrecognised; bool autopower; + int invalid_charger_detect_state; struct ab8500 *parent; struct ab8500_gpadc *gpadc; struct abx500_charger_platform_data *pdata; @@ -650,7 +652,6 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, break; } case USB_STAT_HM_IDGND: - case USB_STAT_NOT_VALID_LINK: dev_err(di->dev, "USB Type - Charging not allowed\n"); di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; ret = -ENXIO; @@ -679,6 +680,9 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, di->max_usb_in_curr); + case USB_STAT_NOT_VALID_LINK: + dev_err(di->dev, "USB Type invalid - try charging anyway\n"); + di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; break; default: @@ -1945,7 +1949,9 @@ static void ab8500_charger_usb_link_attach_work(struct work_struct *work) */ static void ab8500_charger_usb_link_status_work(struct work_struct *work) { + int detected_chargers; int ret; + u8 val; struct ab8500_charger *di = container_of(work, struct ab8500_charger, usb_link_status_work); @@ -1955,11 +1961,66 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work) * synchronously, we have the check if is * connected by reading the status register */ - ret = ab8500_charger_detect_chargers(di); - if (ret < 0) + detected_chargers = ab8500_charger_detect_chargers(di); + if (detected_chargers < 0) return; - if (!(ret & USB_PW_CONN)) { + /* + * Some chargers that breaks the USB spec is + * identified as invalid by AB8500 and it refuse + * to start the charging process. but by jumping + * thru a few hoops it can be forced to start. + */ + ret = abx500_get_register_interruptible(di->dev, AB8500_USB, + AB8500_USB_LINE_STAT_REG, &val); + if (ret >= 0) + dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val); + else + dev_dbg(di->dev, "Error reading USB link status\n"); + + if (detected_chargers & USB_PW_CONN) { + if (((val & AB8500_USB_LINK_STATUS) >> 3) == + USB_STAT_NOT_VALID_LINK && + di->invalid_charger_detect_state == 0) { + dev_dbg(di->dev, + "Invalid charger detected, state= 0\n"); + /*Enable charger*/ + abx500_mask_and_set_register_interruptible(di->dev, + AB8500_CHARGER, + AB8500_USBCH_CTRL1_REG, + 0x01, 0x01) + /*Enable charger detection*/ + abx500_mask_and_set_register_interruptible(di->dev, + AB8500_USB, + AB8500_MCH_IPT_CURLVL_REG, + 0x01, 0x01); + di->invalid_charger_detect_state = 1; + /*exit and wait for new link status interrupt.*/ + return; + + } + if (di->invalid_charger_detect_state == 1) { + dev_dbg(di->dev, + "Invalid charger detected, state= 1\n"); + /*Stop charger detection*/ + abx500_mask_and_set_register_interruptible(di->dev, + AB8500_USB, + AB8500_MCH_IPT_CURLVL_REG, + 0x01, 0x00); + /*Check link status*/ + ret = abx500_get_register_interruptible(di->dev, + AB8500_USB, + AB8500_USB_LINE_STAT_REG, + &val); + dev_dbg(di->dev, "USB link status= 0x%02x\n", + (val & AB8500_USB_LINK_STATUS) >> 3); + di->invalid_charger_detect_state = 2; + } + } else { + di->invalid_charger_detect_state = 0; + } + + if (!(detected_chargers & USB_PW_CONN)) { di->vbus_detected = 0; ab8500_charger_set_usb_connected(di, false); ab8500_power_supply_changed(di, &di->usb_chg.psy); @@ -2862,6 +2923,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) } di->autopower = false; + di->invalid_charger_detect_state = 0; /* AC supply */ /* power_supply base class */