From patchwork Mon Jan 21 12:03:38 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 2011631 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 010BBDF23A for ; Mon, 21 Jan 2013 12:10:45 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TxGAW-0007eh-57; Mon, 21 Jan 2013 12:08:04 +0000 Received: from mail-wi0-f169.google.com ([209.85.212.169]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TxG8J-0006ZK-Tm for linux-arm-kernel@lists.infradead.org; Mon, 21 Jan 2013 12:05:56 +0000 Received: by mail-wi0-f169.google.com with SMTP id hq12so2318955wib.2 for ; Mon, 21 Jan 2013 04:04:23 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=20q91+oEVMi0dN8Il/CX9m+k2R9KdCFz8Xi75q+PKxU=; b=i0CE2KwbOPcORbeVRT8qc5R+EJWLZRnX5o66F1hPrSPJ6Ns2lGQnx2LV3m74aBxLys Ia76dbqncKLvireHHemWPoaptpyPZhGlSiBDz+RZ5tyH/jhh2A/DedaxkM7v9StP1J4p 1HQAf/HotxvbViLDJ9UNYvLaSzBSd02q9/3jsr2PwyCmURYlQkijwa3aWtETVvfC6jja tG58Adi6VbxUEHDwdci+kVuUGWpAItIcTnJXED4lBnDvfxtS2uvrzXBIJeqafy/Qft9M Avc6krdFYUzr3Su1KmM+3JYheQBFGDxnJWAc1tvOqX6aBEn/p2G2CqtccmAWBUPvvKqv ikzw== X-Received: by 10.194.71.244 with SMTP id y20mr25848279wju.19.1358769860531; Mon, 21 Jan 2013 04:04:20 -0800 (PST) Received: from localhost.localdomain (cpc34-aztw25-2-0-cust250.18-1.cable.virginmedia.com. [86.16.136.251]) by mx.google.com with ESMTPS id i2sm16575305wiw.3.2013.01.21.04.04.18 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 21 Jan 2013 04:04:19 -0800 (PST) From: Lee Jones To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 02/24] ab8500-charger: AB workaround for invalid charger Date: Mon, 21 Jan 2013 12:03:38 +0000 Message-Id: <1358769840-4763-3-git-send-email-lee.jones@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1358769840-4763-1-git-send-email-lee.jones@linaro.org> References: <1358769840-4763-1-git-send-email-lee.jones@linaro.org> MIME-Version: 1.0 X-Gm-Message-State: ALoCoQn1796kAs3pPcN2CYfI0z714upXzSBtyRHC+8SoGLGzMTx8T1iXz1K1JoKLwDWigFYEaOBP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130121_070548_235531_92BF247C X-CRM114-Status: GOOD ( 19.30 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.212.169 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linus.walleij@stericsson.com, arnd@arndb.de, cbou@mail.ru, =?UTF-8?q?Henrik=20S=C3=B6lver?= , anton.vorontsov@linaro.org, Lee Jones X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org 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: Lee Jones Signed-off-by: Henrik Sölver Reviewed-by: Yvan FILLION Reviewed-by: Jonas ABERG Tested-by: Yvan FILLION --- drivers/power/ab8500_charger.c | 59 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 43ec82b..4c66172 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -207,6 +207,7 @@ struct ab8500_charger_usb_state { * @usb_device_is_unrecognised USB device is unrecognised by the hardware * @autopower Indicate if we should have automatic pwron after pwrloss * @autopower_cfg platform specific power config support for "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 * @bm: Platform specific battery management information @@ -251,6 +252,7 @@ struct ab8500_charger { bool usb_device_is_unrecognised; bool autopower; bool autopower_cfg; + int invalid_charger_detect_state; struct ab8500 *parent; struct ab8500_gpadc *gpadc; struct abx500_bm_data *bm; @@ -659,7 +661,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; @@ -688,6 +689,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: @@ -1957,7 +1961,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); @@ -1967,11 +1973,55 @@ 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); @@ -2884,6 +2934,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) spin_lock_init(&di->usb_state.usb_lock); di->autopower = false; + di->invalid_charger_detect_state = 0; /* AC supply */ /* power_supply base class */