From patchwork Wed Jun 7 18:37:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liam Breck X-Patchwork-Id: 9772297 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 23A8C6034B for ; Wed, 7 Jun 2017 18:38:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 045E32841C for ; Wed, 7 Jun 2017 18:38:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ED7B9284EA; Wed, 7 Jun 2017 18:38:51 +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=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 EE88D284D4 for ; Wed, 7 Jun 2017 18:38:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752411AbdFGSin (ORCPT ); Wed, 7 Jun 2017 14:38:43 -0400 Received: from mail-pf0-f193.google.com ([209.85.192.193]:35937 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752319AbdFGSil (ORCPT ); Wed, 7 Jun 2017 14:38:41 -0400 Received: by mail-pf0-f193.google.com with SMTP id y7so2403914pfd.3 for ; Wed, 07 Jun 2017 11:38:41 -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=+RBicGCTYGPsG1BF+F22SFIFXUMdHuGHMZoNEIZcnKk=; b=lv5NySs6+qW6affPfDZoDy7hwwDUN4ozXVqrmlY3vCYpDvCWul2RUc09u+We4fXqRB B6Sx3ieL97/bGLPllRwd1j82P2Yxpgo/Zl2jV/XwkEkZG3RCY806ZzSgYxUCTT9hhqV8 +NGCbxZNssR6DCWlI6LcT34PMSOLKzJDxgcSFv4GZRscO3npCEnOvEVm+1iTg+qYXk/g G8zc7rwrVAi+mtu3/iN4xf+AvibBOPKWYiGnqoMhtT+Itd4dZm8bEoX4jyQThUaUHXo/ DmKwNeCAUVqXJmsBqUj+lt7+x5Ox6gb6fulzmkpM8/jWhrGiK4EkIXRDY9kZcJQhtK0S Q+rw== 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=+RBicGCTYGPsG1BF+F22SFIFXUMdHuGHMZoNEIZcnKk=; b=ZdwJ4E733Zu2tnqRufGIUFfSElP5QuuLp8m2CMhg2HR9hMj0B6LiPiZifk0sg8/aMS LD/waC9ea8ILxg/aFpFgJAPGjNgUzI4ya52VypY8yXeH+FRV3522CnvvqLLLvWRq5wpq mUgO0q9J1OxYw/2GpkJlQWkI9yty6aySyM1BFl1y2jeZfOkxurZntF1TVl5BG0YPbNLo 4ICJvdF3rrR1O1P8c/1BVfgrXxIzSUFDDIHNb8RqhFA81mONOiLjy0pseP8/h99QTOy4 v2VVJoVYYa0/Yvs1WuvR73vyANdHCUUnYAeg3omOfipBgF8By3OG+6sNZA1uaOidtJpP FCIg== X-Gm-Message-State: AODbwcDNbreiIvVBDyqRA+kBKBDOIxmyX3ddqlA3j3pYOGZE6q6erFyc EAHqP+Z6uzYtbQ== X-Received: by 10.99.127.78 with SMTP id p14mr34001272pgn.124.1496860710755; Wed, 07 Jun 2017 11:38:30 -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 q85sm319529pfd.7.2017.06.07.11.38.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Jun 2017 11:38:30 -0700 (PDT) From: Liam Breck To: Sebastian Reichel , "Pali Rohar" , linux-pm@vger.kernel.org Cc: Enric Balletbo , Paul Kocialkowski , Quentin Schulz , Matt Ranostay , Liam Breck Subject: [PATCH v14 06/11] power: supply: bq27xxx: Add bulk transfer bus methods Date: Wed, 7 Jun 2017 11:37:54 -0700 Message-Id: <20170607183759.20261-7-liam@networkimprov.net> X-Mailer: git-send-email 2.13.1 In-Reply-To: <20170607183759.20261-1-liam@networkimprov.net> References: <20170607183759.20261-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 398801a2..a11dfad7 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 c68fbc3f..a5972214 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 b312bcef..c3369fa6 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 {