From patchwork Thu May 4 06:18:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liam Breck X-Patchwork-Id: 9710811 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 9B4EF60387 for ; Thu, 4 May 2017 06:19:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8C10728429 for ; Thu, 4 May 2017 06:19:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 810072860E; Thu, 4 May 2017 06:19:28 +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.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham 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 E9F1C285E7 for ; Thu, 4 May 2017 06:19:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753783AbdEDGTY (ORCPT ); Thu, 4 May 2017 02:19:24 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:35766 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753893AbdEDGTN (ORCPT ); Thu, 4 May 2017 02:19:13 -0400 Received: by mail-pg0-f67.google.com with SMTP id i63so878882pgd.2 for ; Wed, 03 May 2017 23:19:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=FDh7xvS/MOyzkcg0CT3LighLbch9XVkoreZawhnplh4=; b=sIcEMOYKK0aJoRH5ArH8pvss2hMQEAinkwdnSPhRjRKaL0oob5e/FcpCAtdD3k2IgA hJ1viZfp/PE+PGGbJ+UkNuouabp5z27zIWQs2w1HxgTDVNE2fVAJb2qkwWYydhJmVytU vKynnHLTFJ59uuRSUBS6nmLOQT0g4tZP/Xno6jjPmMQ/n+hzRSrZWF7DMC6NYIyJWQla S5vGGAL1avHPaKgiwNzJ1Fphqb60T99At0FbNE94gOKSAXRMJm4RJgbPVdEaTN101kfB l1EFW5H0CLXA+00UhTb9eL+X0fTkFOqcfpEAUmp6bE5AGmRMVIZ3F1sXWiH/tAXTN193 Ex/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=FDh7xvS/MOyzkcg0CT3LighLbch9XVkoreZawhnplh4=; b=dK4tjdoUXQGxFtRlFRhML3cWZhaz0F+xMgfsLSjdsvPVy3hYHqCRRJFCUoKmDDEd+9 pw1kwPHeqRm3sgSwsaUrjiWbePoIJ8IZdjB/1qZ5NRQZXJxAeSew0d9OK/xW3bxKgGVL cKKu+3lLjwO6WbSdKkaRWfV3vrlgq5le4j7+5kL5xzCANLS48deuuQMhlWQgbFoI4Gp4 CYIc07626lQsKsES0bpA/7k/zeq1GVXYZSGXGhDuXmYN9gD394JJv3xBKp2mwNaEuc+d ceX/Zd0YLMvcxP4THH9J+FmhzNnX2RD3K7Akfk31PzNEGLGAJ6dsBNbXvAntI3CppMVH /sZg== X-Gm-Message-State: AN3rC/60jKLBtf29Lb/8aQY88lmm5FTYKs/JZKuvjo6x5awlARt58FmU 91emNtmGneE4ldgVrYE= X-Received: by 10.84.169.67 with SMTP id g61mr48664055plb.81.1493878752726; Wed, 03 May 2017 23:19:12 -0700 (PDT) Received: from localhost.localdomain (c-73-223-93-234.hsd1.ca.comcast.net. [73.223.93.234]) by smtp.gmail.com with ESMTPSA id f24sm1870455pfk.88.2017.05.03.23.19.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 03 May 2017 23:19:11 -0700 (PDT) From: Liam Breck To: Sebastian Reichel , "Andrew F. Davis" , linux-pm@vger.kernel.org Cc: Matt Ranostay , Liam Breck Subject: [PATCH v13 06/11] power: supply: bq27xxx_battery: Add bulk transfer bus methods Date: Wed, 3 May 2017 23:18:06 -0700 Message-Id: <20170504061811.18107-7-liam@networkimprov.net> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170504061811.18107-1-liam@networkimprov.net> References: <20170504061811.18107-1-liam@networkimprov.net> 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 From: Matt Ranostay Declare bus.write/read_bulk/write_bulk(). Add I2C write/read_bulk/write_bulk() to implement the above. Add bq27xxx_write/read_block/write_block() helpers to call the above. Signed-off-by: Matt Ranostay Signed-off-by: Liam Breck Acked-by: "Andrew F. Davis" --- drivers/power/supply/bq27xxx_battery.c | 67 +++++++++++++++++++++++- drivers/power/supply/bq27xxx_battery_i2c.c | 82 +++++++++++++++++++++++++++++- include/linux/power/bq27xxx_battery.h | 3 ++ 3 files changed, 149 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index 398801a..a11dfad 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -794,11 +794,74 @@ MODULE_PARM_DESC(poll_interval, static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, bool single) { - /* Reports EINVAL for invalid/missing registers */ + int ret; + if (!di || di->regs[reg_index] == INVALID_REG_ADDR) return -EINVAL; - return di->bus.read(di, di->regs[reg_index], single); + ret = di->bus.read(di, di->regs[reg_index], single); + if (ret < 0) + dev_dbg(di->dev, "failed to read register 0x%02x (index %d)\n", + di->regs[reg_index], reg_index); + + return ret; +} + +static inline int bq27xxx_write(struct bq27xxx_device_info *di, int reg_index, + u16 value, bool single) +{ + int ret; + + if (!di || di->regs[reg_index] == INVALID_REG_ADDR) + return -EINVAL; + + if (!di->bus.write) + return -EPERM; + + ret = di->bus.write(di, di->regs[reg_index], value, single); + if (ret < 0) + dev_dbg(di->dev, "failed to write register 0x%02x (index %d)\n", + di->regs[reg_index], reg_index); + + return ret; +} + +static inline int bq27xxx_read_block(struct bq27xxx_device_info *di, int reg_index, + u8 *data, int len) +{ + int ret; + + if (!di || di->regs[reg_index] == INVALID_REG_ADDR) + return -EINVAL; + + if (!di->bus.read_bulk) + return -EPERM; + + ret = di->bus.read_bulk(di, di->regs[reg_index], data, len); + if (ret < 0) + dev_dbg(di->dev, "failed to read_bulk register 0x%02x (index %d)\n", + di->regs[reg_index], reg_index); + + return ret; +} + +static inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_index, + u8 *data, int len) +{ + int ret; + + if (!di || di->regs[reg_index] == INVALID_REG_ADDR) + return -EINVAL; + + if (!di->bus.write_bulk) + return -EPERM; + + ret = di->bus.write_bulk(di, di->regs[reg_index], data, len); + if (ret < 0) + dev_dbg(di->dev, "failed to write_bulk register 0x%02x (index %d)\n", + di->regs[reg_index], reg_index); + + return ret; } /* diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c index c68fbc3..a597221 100644 --- a/drivers/power/supply/bq27xxx_battery_i2c.c +++ b/drivers/power/supply/bq27xxx_battery_i2c.c @@ -38,7 +38,7 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg, { struct i2c_client *client = to_i2c_client(di->dev); struct i2c_msg msg[2]; - unsigned char data[2]; + u8 data[2]; int ret; if (!client->adapter) @@ -68,6 +68,82 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg, return ret; } +static int bq27xxx_battery_i2c_write(struct bq27xxx_device_info *di, u8 reg, + int value, bool single) +{ + struct i2c_client *client = to_i2c_client(di->dev); + struct i2c_msg msg; + u8 data[4]; + int ret; + + if (!client->adapter) + return -ENODEV; + + data[0] = reg; + if (single) { + data[1] = (u8) value; + msg.len = 2; + } else { + put_unaligned_le16(value, &data[1]); + msg.len = 3; + } + + msg.buf = data; + msg.addr = client->addr; + msg.flags = 0; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) + return ret; + if (ret != 1) + return -EINVAL; + return 0; +} + +static int bq27xxx_battery_i2c_bulk_read(struct bq27xxx_device_info *di, u8 reg, + u8 *data, int len) +{ + struct i2c_client *client = to_i2c_client(di->dev); + int ret; + + if (!client->adapter) + return -ENODEV; + + ret = i2c_smbus_read_i2c_block_data(client, reg, len, data); + if (ret < 0) + return ret; + if (ret != len) + return -EINVAL; + return 0; +} + +static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di, + u8 reg, u8 *data, int len) +{ + struct i2c_client *client = to_i2c_client(di->dev); + struct i2c_msg msg; + u8 buf[33]; + int ret; + + if (!client->adapter) + return -ENODEV; + + buf[0] = reg; + memcpy(&buf[1], data, len); + + msg.buf = buf; + msg.addr = client->addr; + msg.flags = 0; + msg.len = len + 1; + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) + return ret; + if (ret != 1) + return -EINVAL; + return 0; +} + static int bq27xxx_battery_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -95,7 +171,11 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client, di->dev = &client->dev; di->chip = id->driver_data; di->name = name; + di->bus.read = bq27xxx_battery_i2c_read; + di->bus.write = bq27xxx_battery_i2c_write; + di->bus.read_bulk = bq27xxx_battery_i2c_bulk_read; + di->bus.write_bulk = bq27xxx_battery_i2c_bulk_write; ret = bq27xxx_battery_setup(di); if (ret) diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h index b312bce..c3369fa 100644 --- a/include/linux/power/bq27xxx_battery.h +++ b/include/linux/power/bq27xxx_battery.h @@ -40,6 +40,9 @@ struct bq27xxx_platform_data { struct bq27xxx_device_info; struct bq27xxx_access_methods { int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single); + int (*write)(struct bq27xxx_device_info *di, u8 reg, int value, bool single); + int (*read_bulk)(struct bq27xxx_device_info *di, u8 reg, u8 *data, int len); + int (*write_bulk)(struct bq27xxx_device_info *di, u8 reg, u8 *data, int len); }; struct bq27xxx_reg_cache {