From patchwork Mon Dec 12 11:00:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Rosin X-Patchwork-Id: 9470477 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1D3F160476 for ; Mon, 12 Dec 2016 11:34:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0F620281A7 for ; Mon, 12 Dec 2016 11:34:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 03B252823E; Mon, 12 Dec 2016 11:34:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7449D281A7 for ; Mon, 12 Dec 2016 11:34:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752339AbcLLLeL (ORCPT ); Mon, 12 Dec 2016 06:34:11 -0500 Received: from mail-he1eur01on0092.outbound.protection.outlook.com ([104.47.0.92]:55110 "EHLO EUR01-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751252AbcLLLeJ (ORCPT ); Mon, 12 Dec 2016 06:34:09 -0500 X-Greylist: delayed 1982 seconds by postgrey-1.27 at vger.kernel.org; Mon, 12 Dec 2016 06:34:08 EST DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axentiatech.onmicrosoft.com; s=selector1-axentia-se; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=4hAueBcjkQjrJDDzJm5PXNoraylTINxjYKe9Rgqz9xg=; b=HLwPqVrAc0uyE+Zr9i+im1Vrm5twc9xsXFe7393ieLXcQ95HRF0Uh6lDmvCNx9d+TICXissN4pdxOLqyno+IeN5HMb/tSn/dduapCQicj+kg5qlp/aapiGucASsW15A1r2WTSkcfrlKNmOBCxc50dsoWHKAD50aboj3FbVSC4w4= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=peda@axentia.se; Received: from localhost.localdomain (217.210.101.82) by DB6PR0201MB2309.eurprd02.prod.outlook.com (10.169.222.148) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.771.8; Mon, 12 Dec 2016 11:01:10 +0000 From: Peter Rosin To: linux-kernel@vger.kernel.org Cc: Peter Rosin , Sebastian Reichel , Rob Herring , Mark Rutland , linux-pm@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH 3/3] power: supply: bq24735-charger: allow chargers to share the ac-detect gpio Date: Mon, 12 Dec 2016 12:00:24 +0100 Message-Id: <1481540424-19293-4-git-send-email-peda@axentia.se> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1481540424-19293-1-git-send-email-peda@axentia.se> References: <1481540424-19293-1-git-send-email-peda@axentia.se> MIME-Version: 1.0 X-Originating-IP: [217.210.101.82] X-ClientProxiedBy: DB6PR0701CA0027.eurprd07.prod.outlook.com (10.168.7.165) To DB6PR0201MB2309.eurprd02.prod.outlook.com (10.169.222.148) X-MS-Office365-Filtering-Correlation-Id: fc32b33e-bd4e-4a77-e05d-08d4227e2e98 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:DB6PR0201MB2309; X-Microsoft-Exchange-Diagnostics: 1; DB6PR0201MB2309; 3:f7oxrHGo3Y3ia6FHm4inEsGqoyI91VWRvr4RHRN5QnbYqvkqpprEeU8mIGp0q3KMgkraH/xyJ9P0T5jw/rx6QEhf25qwy0zYeSFU5ytcHiBcRWH0ABaKIph5iV3LpGqp3UFPL9vR5q3pAQ+OPrh13TRAoB1NBF0F9Q0SRmzOmbqOVMzZvPQwB349maZc/fkHCgr9Hs0njLHtEJbHyNJCaXY1ZsB9qbDP5dHDtJokF24HQNB9KJEHDiEJX45HsTNplsLebqhRxuNoiFJv27i0ZQ==; 25:rOY7WqvDzgDjCpqWVdvaVNnnbObjtI4ZGkvt0jiT0TKWiFUY2WS1GXEwZVgpkStjtk9f0G3eKr5XhX4+VFYPetr5mUhblWWDgJ65brKEBdcSHpXj5AyFU4otJSLc7u/8yUEqe00k+XP6KYqjKKnTa1oY99rKNoBql4D6HYyvBa0ibfsrSDqC3nrNTfKE81oJXmT37ygiBb/0eArYFQo+8fezRaD4ts0tU+M7k3baQM8SjcnT7Mh78/8G8H9PegaXd8oz0F8j+EzC+ukGfsO2JHA1YxUidVkclBguPNWsvMM5R3GXHZWMX5FLs+Fkdi0eeRieX/RY9j5gxmQE15M1AOD0RGdRiHMZGj4KjmSAvoEL5/jow1Fo8VFPM/vPK4A17QGLnRt/zkLbJbPA6bGhTJvOTaj+a2owQCC+vETn4kxq+Ia+GXFac7pX5516T8JJ0og7laV0w06gzYAQVRs6IQ== X-Microsoft-Exchange-Diagnostics: 1; DB6PR0201MB2309; 31:5b40aEpZlhH+bIugGivFncblnpcDnNnxTMfNYYn7jQJX6v+nj6Q+yrLzEYyaNFCQKc4qm2ihdSK63X1hv74+/g3/oxs5XdmR8bYAFpP1yEybq5yG9rggufa8QARLWrL+U1VwS96FQTviV4a4JkMslRXhfqnGkWtWRFwdCKGgfcH1nn8lUkbcIFn7vDOqb5KyHz4EWTJY8oBSPRqSq8c8U7QnmoMeJ4FSar7bPrXbx2YR8yqPP/yo5s1dUO4tVzDN; 4:XiX6GAnUz+x/XOIWXTKaseh3h3QzJKn6CxaShfa4Cu0kmiCbdHXrYpHsDLiQseUTP9rP+zw+8nGl6y8Ziib9RgHBcjWeBZUiHK30Mpl+HMa2vQsBJeeA/oJLc+z5A29z/M3ebr9yT9s567FjbvQNATjHaTNkyLPOUDGNAxB/Gdqc0m29CtQk6BgGjkVqlOF3WSdHudx3Vthe73E/2yKVRK86DT8wK5IVJS52nOY5sKKlvb0wxJXKLQikq1TZRBYExf/CTCUgjxpSXOPdxtZ7m1r/9+C99oIGRXu/DEolg3OnJ9v4f/daPZu9Qolem3eaB6lPPF2JWHNeZO6oz+qCjPYFKGj8Tj7fZENg8IPKIrgldg/2YJZG21qjPC4h6DKi+bJWRDJER+OrEOO5r3BRKbE8EAJmnDCfMScFfZSZc6tFua6LP5YX3905meEbyNNB6X5hIec4OpkwZ/YTSwBBXt8xtpkRgObMIkyzeBXPhWDCa8Go4bBIXQJ+ingSP/mrk90Hvsn7mlGcD//VNT+JTLWoPl+hOqiZnufDQIokYUFJUncpTlsnw3eFPUGfosZICC6bwnq8ojHmrkdMdSwTIHzH+9vRuXS/xgDgGre1TidmVANKGtZqiEE4f393GiLU X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040375)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046)(6041248)(2016111802025)(20161123555025)(20161123560025)(20161123564025)(20161123562025)(6043046)(6072148); SRVR:DB6PR0201MB2309; BCL:0; PCL:0; RULEID:; SRVR:DB6PR0201MB2309; X-Forefront-PRVS: 0154C61618 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(6069001)(7916002)(39450400003)(39830400002)(39410400002)(189002)(199003)(36756003)(2950100002)(5660300001)(48376002)(97736004)(50466002)(2361001)(7736002)(68736007)(106356001)(86362001)(305945005)(76176999)(105586002)(2906002)(92566002)(50986999)(74482002)(50226002)(5003940100001)(6916009)(8676002)(6512006)(42186005)(33646002)(189998001)(2351001)(81166006)(4326007)(6506006)(81156014)(6486002)(110136003)(3846002)(6116002)(66066001)(38730400001)(47776003)(101416001)(6666003)(42262002); DIR:OUT; SFP:1102; SCL:1; SRVR:DB6PR0201MB2309; H:localhost.localdomain; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: axentia.se does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DB6PR0201MB2309; 23:2N7E23RRBL9XqRrGXyZDg6c6ytQ2p12YPklBjC5?= =?us-ascii?Q?yg2ygJmyQ0Ri6wak5ZTf3UhDKvwyCLKTKPJK3FumaXuQAAH2ZHKSHDN5FM/A?= =?us-ascii?Q?3keHm5+Uzq5xaHS7K8zk7HMOqDIVCC60noe8393QXMqJkd2rPr1JI/5De2dW?= =?us-ascii?Q?teLNVtpy7Pp5XdPDIrvqeOMdeXa3WP9OJbC71IM8UKeTNinLEwE6YIq5OCpR?= =?us-ascii?Q?yOf/O0vPw3DdhIie11R448COfC7Bnzh9i2G4I5cIItQfWKYu8Q7xhLacxMVf?= =?us-ascii?Q?0pJqqPAfGs2CEPsb1NwXPXHHKAEmbKrvhdPZDyBhO9Cgr1hlXjZs32i8AIX5?= =?us-ascii?Q?la7ccXwNdwkacOINSrlm5Y6H7vtR+M8MTwabljA66oKlZO2E+Vop6gZ9Lxvu?= =?us-ascii?Q?Kh8m/SFqm0cnSy0kcn+NrX1q5L7flWWuJK4WZli2ym/Rbrg9bCZjH6BsFOwD?= =?us-ascii?Q?c6aHrrg0SI9cVA6tUBBgRXPrsyA1ab2Zq/Xa+n4Jkqbgg0Hm+RzfTH/kcDYO?= =?us-ascii?Q?VLvuho2zViQNmz0w2H9OgUHsnfr+/upmD+2+l2wVDlVlUVcBf4SwQ3aJQVpc?= =?us-ascii?Q?ysjARanWeUO0liXI/mIPYl9A5SjuaTo+DRDeOvEzNvC5p3JNpEszQN9BnBCB?= =?us-ascii?Q?Ojq+D7d2ImNcgHROFCX/Qj1+kUZbu+TKIhO0J4XnHcTktLz4g7hZqpVgconP?= =?us-ascii?Q?tWpZHoDaMiqm3tocCZaCWBazB6Cu2hoy84XK9lVMXBq0MOFhbnutF0TKlywb?= =?us-ascii?Q?NoJJJ5ygXKr2KQbv+bSd5wzf+EJ9Kdj7WciaTB7lZuIrlYncXMYydenA4QQt?= =?us-ascii?Q?UDmSeC0DOutLz2B4qW/bv/JaGcMyHREMklVnGKfB8xQjfiWBZSpWZIMz/r6r?= =?us-ascii?Q?OQbmyquZKPUa8MmjTRNgbb8Gjia9QHXy+kEl8rXd4TrgeAnlofUiebB3s4a6?= =?us-ascii?Q?vBIwyTDybNnKViv1q+A9wmKVzDnb+4RMShY0Xx2zpmyf/tCTqg3QK6Q3vtll?= =?us-ascii?Q?MksfH4W60Ov4//2+ttNW+rQWoJGBVo9kEroYwuGueYWrjWn0FU9Zi6KwU1uV?= =?us-ascii?Q?zH+suvcADoNybfdmjtLTlA2Q0i8b8ckogyxQtHe9sAOhimuCNRqQsg6wfrJ8?= =?us-ascii?Q?eO+EKnspLvin9uBoabJMSMYbm2tUytiqGEv+nhok1FxgXntmpvahunpgx+B0?= =?us-ascii?Q?sPzbeLxHqMuRbkVTvM4/BckpE26K7vTge4tbt?= X-Microsoft-Exchange-Diagnostics: 1; DB6PR0201MB2309; 6:K/Hmp5BqN2ZJHVompK2EtDR9DZJ7MCSsZ2lPMsuyXrGlQx+Ly/0K65ZLXYQXMB9/JBUbuSG8SJRbYG7Xg2apQwifNX+oXPwvCTflKWsMc/mdK/6ejEQni4P2nd0duMwEQC4DRONSDMZMWa1HGp0N+b5Bbzi5Q60BNf+XTeYucuPA1ahNtN9qbVWuslrqyMJ/DDq1yNiFPsWUnwWyQRIJfKHyWK4G8bxQ75pbsz/p50pdT3rzJFkjUtUnSF+vB0HzK1QdBeX3p1RT1wAllwtorPt3AlLNfDnVtxUTIO4DTCtkvz9lQpAnvkxh+9TTwriqVzQ29j4FlmpWpasQcJEQ3dXgXZws1V4DM/EL9dV7biN1rvRAwy1NqqX4adDdIit2MKuHXaXYIE6LuXVqS6Cz6+NMLLeAAbL5LQUxwM4zkEsccBts4WoXzFENym97TD28; 5:Wgg4pB7KHyfXH3NgblpFnNC/bOcAXcd2EoxfzqWoCgA5KEdEc/SvvnqI5jaogBWmgioS+6jeMUFUOCn0Y51FE1ZGlZ5zKK9MN6PBYQqtdmiov0wTWCJ2j6n1Wd0gerUpc19E1C+6PPDbl2SDGtt/Mq98zSB1MlDyBhOlOPvxJdc=; 24:svcuEuufTM1oBTqaLFXJ1k1jFauVxemZIiSxNcsVigrEGLJfaEHOaVK7zgrcTqm7b/lLCJndb3bugjY6ubysgIqgfFjWnqcB5kEahC8eB88= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DB6PR0201MB2309; 7:Z4hG+2T3QZxumPlOJ1YsLBl4kUfYPL54ec1oazUCg7k5MK4rtjl4wEKST5r+IQRWX95uxNYnegfFTZE6KBIftfpr9hWGY5GtzNE+xwuV6YlHG3JYWhZGA1vN3V9uuV4SGVFh+oA3K8f/TZzsGcLCwAdjDePZRhz20384ZkOESeRvjJQ8agaEGEUKkoPnQtozd9DRwMoknNSw5TcLVVIwaAZV3KNxzNMR3TZpKXKTnSxw9RoiKLdOSFDtxFq88GRmEqW9Otuq5KbG+DJ1toYm6giIp7zq+Brb5uxy8tBZWMlr3CFlCW8d206k8RNrXeWdBtkxmUcAlRii/imspVKZLNr6qzNrb/jXhAsd9Z4w3jmodv3Z4CjkbxZ/5MaybEozDBRtdXyVqd2YlnsfsCAhH+7pcVNO7m1jI7PWXOBt+wKFcERZBPb4nXgDQq5ET4C1OcOvK2kqjaGMbm8eX41MPA== X-OriginatorOrg: axentia.se X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Dec 2016 11:01:10.0259 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0201MB2309 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If several parallel bq24735 chargers have their ac-detect gpios wired together (or if only one of the parallel bq24735 chargers have its ac-detect pin wired to a gpio, and the others are assumed to react the same), then all driver instances need to check the same gpio. But the gpio subsystem does not allow sharing gpios, so handle that locally. However, only do this for the polling case, sharing is not supported if the ac detection is handled with interrupts. Signed-off-by: Peter Rosin --- drivers/power/supply/bq24735-charger.c | 101 +++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 11 deletions(-) diff --git a/drivers/power/supply/bq24735-charger.c b/drivers/power/supply/bq24735-charger.c index 3765806d5d46..3b21a064a9a7 100644 --- a/drivers/power/supply/bq24735-charger.c +++ b/drivers/power/supply/bq24735-charger.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -43,12 +44,24 @@ #define BQ24735_MANUFACTURER_ID 0xfe #define BQ24735_DEVICE_ID 0xff +struct bq24735; + +struct bq24735_shared { + struct list_head list; + struct bq24735 *owner; + struct gpio_desc *status_gpio; +}; + +static struct mutex shared_lock; +static LIST_HEAD(shared_list); + struct bq24735 { struct power_supply *charger; struct power_supply_desc charger_desc; struct i2c_client *client; struct bq24735_platform *pdata; struct mutex lock; + struct bq24735_shared *shared; struct gpio_desc *status_gpio; struct delayed_work poll; u32 poll_interval; @@ -346,6 +359,65 @@ static struct bq24735_platform *bq24735_parse_dt_data(struct i2c_client *client) return pdata; } +static struct gpio_desc *bq24735_get_status_gpio(struct bq24735 *charger) +{ + struct device *dev = &charger->client->dev; + struct bq24735_shared *shared; + int gpio; + struct list_head *pos; + + if (!of_property_read_bool(dev->of_node, "ti,ac-detect-gpios")) + return NULL; + + gpio = of_get_named_gpio(dev->of_node, "ti,ac-detect-gpios", 0); + if (gpio < 0) + return ERR_PTR(gpio); + + mutex_lock(&shared_lock); + list_for_each(pos, &shared_list) { + shared = list_entry(pos, struct bq24735_shared, list); + if (gpio != desc_to_gpio(shared->status_gpio)) + continue; + + get_device(&shared->owner->client->dev); + dev_dbg(dev, "sharing gpio with %s\n", + shared->owner->pdata->name); + charger->shared = shared; + mutex_unlock(&shared_lock); + return shared->status_gpio; + } + + shared = devm_kzalloc(dev, sizeof(*shared), GFP_KERNEL); + if (!shared) { + mutex_unlock(&shared_lock); + return ERR_PTR(-ENOMEM); + } + shared->owner = charger; + shared->status_gpio = gpiod_get(dev, "ti,ac-detect", GPIOD_IN); + if (!IS_ERR(shared->status_gpio)) { + charger->shared = shared; + list_add(&shared->list, &shared_list); + } + mutex_unlock(&shared_lock); + + return shared->status_gpio; +} + +static void bq24735_put_status_gpio(struct bq24735 *charger) +{ + if (!charger->shared) + return; + + mutex_lock(&shared_lock); + if (charger->shared->owner != charger) { + put_device(&charger->shared->owner->client->dev); + } else { + list_del(&charger->shared->list); + gpiod_put(charger->shared->status_gpio); + } + mutex_unlock(&shared_lock); +} + static int bq24735_charger_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -402,9 +474,7 @@ static int bq24735_charger_probe(struct i2c_client *client, i2c_set_clientdata(client, charger); - charger->status_gpio = devm_gpiod_get_optional(&client->dev, - "ti,ac-detect", - GPIOD_IN); + charger->status_gpio = bq24735_get_status_gpio(charger); if (IS_ERR(charger->status_gpio)) { ret = PTR_ERR(charger->status_gpio); dev_err(&client->dev, "Getting gpio failed: %d\n", ret); @@ -416,28 +486,30 @@ static int bq24735_charger_probe(struct i2c_client *client, if (ret < 0) { dev_err(&client->dev, "Failed to read manufacturer id : %d\n", ret); - return ret; + goto out; } else if (ret != 0x0040) { dev_err(&client->dev, "manufacturer id mismatch. 0x0040 != 0x%04x\n", ret); - return -ENODEV; + ret = -ENODEV; + goto out; } ret = bq24735_read_word(client, BQ24735_DEVICE_ID); if (ret < 0) { dev_err(&client->dev, "Failed to read device id : %d\n", ret); - return ret; + goto out; } else if (ret != 0x000B) { dev_err(&client->dev, "device id mismatch. 0x000b != 0x%04x\n", ret); - return -ENODEV; + ret = -ENODEV; + goto out; } } ret = bq24735_config_charger(charger); if (ret < 0) { dev_err(&client->dev, "failed in configuring charger"); - return ret; + goto out; } /* check for AC adapter presence */ @@ -445,7 +517,7 @@ static int bq24735_charger_probe(struct i2c_client *client, ret = bq24735_enable_charging(charger); if (ret < 0) { dev_err(&client->dev, "Failed to enable charging\n"); - return ret; + goto out; } } @@ -455,7 +527,7 @@ static int bq24735_charger_probe(struct i2c_client *client, ret = PTR_ERR(charger->charger); dev_err(&client->dev, "Failed to register power supply: %d\n", ret); - return ret; + goto out; } if (client->irq) { @@ -470,7 +542,7 @@ static int bq24735_charger_probe(struct i2c_client *client, dev_err(&client->dev, "Unable to register IRQ %d err %d\n", client->irq, ret); - return ret; + goto out; } } else if (charger->status_gpio) { ret = of_property_read_u32(client->dev.of_node, @@ -487,6 +559,11 @@ static int bq24735_charger_probe(struct i2c_client *client, } return 0; + +out: + bq24735_put_status_gpio(charger); + + return ret; } static int bq24735_charger_remove(struct i2c_client *client) @@ -496,6 +573,8 @@ static int bq24735_charger_remove(struct i2c_client *client) if (charger->poll_interval) cancel_delayed_work_sync(&charger->poll); + bq24735_put_status_gpio(charger); + return 0; }