From patchwork Fri Mar 17 09:55:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 740217 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3vl19J3JWgz9s0Z for ; Fri, 17 Mar 2017 21:02:28 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751425AbdCQJ7L (ORCPT ); Fri, 17 Mar 2017 05:59:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60428 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751061AbdCQJ4t (ORCPT ); Fri, 17 Mar 2017 05:56:49 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EA1137AEA1; Fri, 17 Mar 2017 09:56:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com EA1137AEA1 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=hdegoede@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com EA1137AEA1 Received: from shalem.localdomain.com (ovpn-116-172.ams2.redhat.com [10.36.116.172]) by smtp.corp.redhat.com (Postfix) with ESMTP id 80DAB5C3FA; Fri, 17 Mar 2017 09:55:58 +0000 (UTC) From: Hans de Goede To: "Rafael J . Wysocki" , Len Brown , Wolfram Sang , Andy Shevchenko , Lee Jones , Sebastian Reichel , MyungJoo Ham , Chanwoo Choi Cc: Hans de Goede , linux-acpi@vger.kernel.org, Takashi Iwai , linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org Subject: [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost Date: Fri, 17 Mar 2017 10:55:22 +0100 Message-Id: <20170317095527.10487-11-hdegoede@redhat.com> In-Reply-To: <20170317095527.10487-1-hdegoede@redhat.com> References: <20170317095527.10487-1-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Fri, 17 Mar 2017 09:56:01 +0000 (UTC) Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Add support for monitoring an extcon device with SDP/CDP/DCP and HOST cables and adjust ilimit and enable/disable the 5v boost converter accordingly. This is necessary on systems where the PSEL pin is hardwired high and ILIM needs to be set by software based on the detected charger type. Signed-off-by: Hans de Goede Acked-By: Sebastian Reichel --- drivers/power/supply/Kconfig | 1 + drivers/power/supply/bq24190_charger.c | 85 ++++++++++++++++++++++++++++++++++ include/linux/power/bq24190_charger.h | 1 + 3 files changed, 87 insertions(+) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index f8b6e64..fd93110 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -442,6 +442,7 @@ config CHARGER_BQ2415X config CHARGER_BQ24190 tristate "TI BQ24190 battery charger driver" depends on I2C + depends on EXTCON depends on GPIOLIB || COMPILE_TEST help Say Y to enable support for the TI BQ24190 battery charger. diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 82cb33d..03990e2 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -11,10 +11,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -39,6 +41,8 @@ #define BQ24190_REG_POC_WDT_RESET_SHIFT 6 #define BQ24190_REG_POC_CHG_CONFIG_MASK (BIT(5) | BIT(4)) #define BQ24190_REG_POC_CHG_CONFIG_SHIFT 4 +#define BQ24190_REG_POC_CHG_CONFIG_CHARGE 1 +#define BQ24190_REG_POC_CHG_CONFIG_OTG 2 #define BQ24190_REG_POC_SYS_MIN_MASK (BIT(3) | BIT(2) | BIT(1)) #define BQ24190_REG_POC_SYS_MIN_SHIFT 1 #define BQ24190_REG_POC_BOOST_LIM_MASK BIT(0) @@ -152,6 +156,9 @@ struct bq24190_dev_info { struct power_supply *charger; struct power_supply *battery; struct bq24190_platform_data *pdata; + struct extcon_dev *extcon; + struct notifier_block extcon_nb; + struct work_struct extcon_work; char model_name[I2C_NAME_SIZE]; kernel_ulong_t model; struct mutex f_reg_lock; @@ -167,6 +174,11 @@ struct bq24190_dev_info { * number at that index in the array is the real-world value that it * represents. */ + +/* REG00[2:0] (IINLIM) in uAh */ +static const int bq24190_iinlim_values[] = { + 100000, 150000, 500000, 900000, 1200000, 1500000, 2000000, 3000000 }; + /* REG02[7:2] (ICHG) in uAh */ static const int bq24190_ccc_ichg_values[] = { 512000, 576000, 640000, 704000, 768000, 832000, 896000, 960000, @@ -1290,6 +1302,61 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) return IRQ_HANDLED; } +static void bq24190_extcon_work(struct work_struct *work) +{ + struct bq24190_dev_info *bdi = + container_of(work, struct bq24190_dev_info, extcon_work); + int ret, iinlim = 0; + + if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_SDP) == 1) + iinlim = 500000; + else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_CDP) == 1 || + extcon_get_state(bdi->extcon, EXTCON_CHG_USB_ACA) == 1) + iinlim = 1500000; + else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_DCP) == 1) + iinlim = 2000000; + + if (iinlim) { + ret = bq24190_set_field_val(bdi, BQ24190_REG_ISC, + BQ24190_REG_ISC_IINLIM_MASK, + BQ24190_REG_ISC_IINLIM_SHIFT, + bq24190_iinlim_values, + ARRAY_SIZE(bq24190_iinlim_values), + iinlim); + if (ret) + dev_err(bdi->dev, "Can't set IINLIM: %d\n", ret); + } + + /* + * If no charger has been detected and host mode is requested, activate + * the 5V boost converter, otherwise deactivate it. + */ + if (!iinlim && extcon_get_state(bdi->extcon, EXTCON_USB_HOST) == 1) { + ret = bq24190_write_mask(bdi, BQ24190_REG_POC, + BQ24190_REG_POC_CHG_CONFIG_MASK, + BQ24190_REG_POC_CHG_CONFIG_SHIFT, + BQ24190_REG_POC_CHG_CONFIG_OTG); + } else { + ret = bq24190_write_mask(bdi, BQ24190_REG_POC, + BQ24190_REG_POC_CHG_CONFIG_MASK, + BQ24190_REG_POC_CHG_CONFIG_SHIFT, + BQ24190_REG_POC_CHG_CONFIG_CHARGE); + } + if (ret) + dev_err(bdi->dev, "Can't set CHG_CONFIG: %d\n", ret); +} + +static int bq24190_extcon_event(struct notifier_block *nb, unsigned long event, + void *param) +{ + struct bq24190_dev_info *bdi = + container_of(nb, struct bq24190_dev_info, extcon_nb); + + schedule_work(&bdi->extcon_work); + + return NOTIFY_OK; +} + static int bq24190_hw_init(struct bq24190_dev_info *bdi) { u8 v; @@ -1375,6 +1442,12 @@ static int bq24190_probe(struct i2c_client *client, return -EPROBE_DEFER; } + if (bdi->pdata && bdi->pdata->extcon_name) { + bdi->extcon = extcon_get_extcon_dev(bdi->pdata->extcon_name); + if (!bdi->extcon) + return -EPROBE_DEFER; + } + pm_runtime_enable(dev); pm_runtime_resume(dev); @@ -1423,6 +1496,18 @@ static int bq24190_probe(struct i2c_client *client, goto out4; } + if (bdi->extcon) { + INIT_WORK(&bdi->extcon_work, bq24190_extcon_work); + bdi->extcon_nb.notifier_call = bq24190_extcon_event; + ret = devm_extcon_register_notifier(dev, bdi->extcon, -1, + &bdi->extcon_nb); + if (ret) + goto out4; + + /* Sync initial cable state */ + schedule_work(&bdi->extcon_work); + } + return 0; out4: diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h index 02d248b..909c5b9 100644 --- a/include/linux/power/bq24190_charger.h +++ b/include/linux/power/bq24190_charger.h @@ -13,6 +13,7 @@ struct bq24190_platform_data { bool no_register_reset; + const char *extcon_name; int (*get_ext_bat_property)(enum power_supply_property prop, union power_supply_propval *val); };