From patchwork Mon Jan 21 12:03:55 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Jones X-Patchwork-Id: 14164 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 902A423E33 for ; Mon, 21 Jan 2013 12:05:09 +0000 (UTC) Received: from mail-vc0-f175.google.com (mail-vc0-f175.google.com [209.85.220.175]) by fiordland.canonical.com (Postfix) with ESMTP id 33E98A18EFB for ; Mon, 21 Jan 2013 12:05:09 +0000 (UTC) Received: by mail-vc0-f175.google.com with SMTP id fw7so2885160vcb.34 for ; Mon, 21 Jan 2013 04:05:08 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-received:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state; bh=JboUGrxbeYrbMeexa8Ogt1Q4Irgpu0Ron78eYEVhXJM=; b=Tr7IcRlA3fxxySeQNs7yrQ1Y6SXD7sXJgs+709zs7aajkiKdsgBMKIr/7Wm/iFO/S7 yjGULPT2cIsgKWA5qGiRecytLL+TOSQ408QhVGGOcnYRQK736+txrLBXG4jEe5wXJKsQ UpFShhO/rzUBpCghfdzC5IyFpJkzjXbZolodF4aDocmOzkz1Cv6CDoYlTXnir4VP5s/H 6lz6GfJW1S0EUEfs74qTlf0SYJ9VQXqjmK3FlcSxcIQFIonNHPXl+n9AVTqN8dyWf0jZ HKRdnMv0VmLVMo4zDQoIXTe8AsM0RXQzGguIyqh98IFp9S3wSBc2Ra7nmUju+Tzn4C7C VAcA== X-Received: by 10.220.154.199 with SMTP id p7mr18855695vcw.48.1358769908720; Mon, 21 Jan 2013 04:05:08 -0800 (PST) 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.58.145.101 with SMTP id st5csp197744veb; Mon, 21 Jan 2013 04:05:07 -0800 (PST) X-Received: by 10.180.19.99 with SMTP id d3mr14978948wie.4.1358769896679; Mon, 21 Jan 2013 04:04:56 -0800 (PST) Received: from mail-wi0-f173.google.com (mail-wi0-f173.google.com [209.85.212.173]) by mx.google.com with ESMTPS id bo15si3811918wib.73.2013.01.21.04.04.56 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 21 Jan 2013 04:04:56 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.173 is neither permitted nor denied by best guess record for domain of lee.jones@linaro.org) client-ip=209.85.212.173; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.173 is neither permitted nor denied by best guess record for domain of lee.jones@linaro.org) smtp.mail=lee.jones@linaro.org Received: by mail-wi0-f173.google.com with SMTP id hn17so7064480wib.0 for ; Mon, 21 Jan 2013 04:04:56 -0800 (PST) X-Received: by 10.180.20.109 with SMTP id m13mr15050818wie.16.1358769896259; Mon, 21 Jan 2013 04:04:56 -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.54 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 21 Jan 2013 04:04:55 -0800 (PST) From: Lee Jones To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: arnd@arndb.de, linus.walleij@stericsson.com, anton.vorontsov@linaro.org, cbou@mail.ru, Rupesh Kumar , Lee Jones Subject: [PATCH 19/24] pm2301: LPN mode control support Date: Mon, 21 Jan 2013 12:03:55 +0000 Message-Id: <1358769840-4763-20-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> X-Gm-Message-State: ALoCoQkL5CsE3Rwf1sWiu/Y+mPyzYIhxPtwlyrEwU99n+c9etb4y/kmuHg34xPUs2xeA//MRQ9Qo From: Rupesh Kumar The AC charger plug-in detection while booting causes I2C read failure if AC charger is not connected. Now the LPN pin is enabled for every PM2301 register access, which solves the issue. Signed-off-by: Lee Jones Signed-off-by: Rupesh Kumar Reviewed-by: Marcus COOPER Reviewed-by: Vijaya Kumar K-1 Reviewed-by: Rabin VINCENT Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- drivers/power/pm2301_charger.c | 72 ++++++++++++++++++++++++++++++++++++++-- drivers/power/pm2301_charger.h | 1 + include/linux/pm2301_charger.h | 1 + 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c index c7d92b3..14e37b2 100644 --- a/drivers/power/pm2301_charger.c +++ b/drivers/power/pm2301_charger.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "pm2301_charger.h" @@ -110,9 +111,35 @@ static const struct i2c_device_id pm2xxx_ident[] = { { } }; +static void set_lpn_pin(struct pm2xxx_charger *pm2) +{ + if (pm2->ac.charger_connected) + return; + gpio_set_value(pm2->lpn_pin, 1); + + return; +} + +static void clear_lpn_pin(struct pm2xxx_charger *pm2) +{ + if (pm2->ac.charger_connected) + return; + gpio_set_value(pm2->lpn_pin, 0); + + return; +} + int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val) { int ret; + /* + * When AC adaptor is unplugged, the host + * must put LPN high to be able to + * communicate by I2C with PM2301 + * and receive I2C "acknowledge" from PM2301. + */ + mutex_lock(&pm2->lock); + set_lpn_pin(pm2); ret = i2c_smbus_read_i2c_block_data(pm2->config.pm2xxx_i2c, reg, 1, val); @@ -120,6 +147,8 @@ int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val) dev_err(pm2->dev, "Error reading register at 0x%x\n", reg); else ret = 0; + clear_lpn_pin(pm2); + mutex_unlock(&pm2->lock); return ret; } @@ -127,6 +156,14 @@ int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val) int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val) { int ret; + /* + * When AC adaptor is unplugged, the host + * must put LPN high to be able to + * communicate by I2C with PM2301 + * and receive I2C "acknowledge" from PM2301. + */ + mutex_lock(&pm2->lock); + set_lpn_pin(pm2); ret = i2c_smbus_write_i2c_block_data(pm2->config.pm2xxx_i2c, reg, 1, &val); @@ -134,6 +171,8 @@ int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val) dev_err(pm2->dev, "Error writing register at 0x%x\n", reg); else ret = 0; + clear_lpn_pin(pm2); + mutex_unlock(&pm2->lock); return ret; } @@ -850,6 +889,14 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, pm2->bat = pl_data->battery; + /*get lpn GPIO from platform data*/ + if (!pm2->pdata->lpn_gpio) { + dev_err(pm2->dev, "no lpn gpio data supplied\n"); + ret = -EINVAL; + goto free_device_info; + } + pm2->lpn_pin = pm2->pdata->lpn_gpio; + if (!i2c_check_functionality(i2c_client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_READ_WORD_DATA)) { @@ -929,10 +976,25 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, goto unregister_pm2xxx_charger; } + /*Initialize lock*/ + mutex_init(&pm2->lock); + /* - * I2C Read/Write will fail, if AC adaptor is not connected. - * fix the charger detection mechanism. + * Charger detection mechanism requires pulling up the LPN pin + * while i2c communication if Charger is not connected + * LPN pin of PM2301 is GPIO60 of AB9540 */ + ret = gpio_request(pm2->lpn_pin, "pm2301_lpm_gpio"); + if (ret < 0) { + dev_err(pm2->dev, "pm2301_lpm_gpio request failed\n"); + goto unregister_pm2xxx_charger; + } + ret = gpio_direction_output(pm2->lpn_pin, 0); + if (ret < 0) { + dev_err(pm2->dev, "pm2301_lpm_gpio direction failed\n"); + goto free_gpio; + } + ret = pm2xxx_charger_detection(pm2, &val); if ((ret == 0) && val) { @@ -951,7 +1013,8 @@ static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, err_deep_debug: /* disable interrupt */ free_irq(pm2->pdata->irq_number, pm2); - +free_gpio: + gpio_free(pm2->lpn_pin); unregister_pm2xxx_charger: /* unregister power supply */ power_supply_unregister(&pm2->ac_chg.psy); @@ -987,6 +1050,9 @@ static int __devexit pm2xxx_wall_charger_remove(struct i2c_client *i2c_client) power_supply_unregister(&pm2->ac_chg.psy); + /*Free GPIO60*/ + gpio_free(pm2->lpn_pin); + kfree(pm2); return 0; diff --git a/drivers/power/pm2301_charger.h b/drivers/power/pm2301_charger.h index 5ae3573..c28babc 100644 --- a/drivers/power/pm2301_charger.h +++ b/drivers/power/pm2301_charger.h @@ -493,6 +493,7 @@ struct pm2xxx_charger { int old_vbat; int failure_case; int failure_input_ovv; + unsigned int lpn_pin; struct pm2xxx_interrupts *pm2_int; struct ab8500_gpadc *gpadc; struct regulator *regu; diff --git a/include/linux/pm2301_charger.h b/include/linux/pm2301_charger.h index 16bb1d3..fc3f026 100644 --- a/include/linux/pm2301_charger.h +++ b/include/linux/pm2301_charger.h @@ -49,6 +49,7 @@ struct pm2xxx_charger_platform_data { int i2c_bus; const char *label; int irq_number; + unsigned int lpn_gpio; int irq_type; };