From patchwork Sat Mar 24 20:05:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brian Masney X-Patchwork-Id: 10306353 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 A54FD600CC for ; Sat, 24 Mar 2018 20:06:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9544B29272 for ; Sat, 24 Mar 2018 20:06:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 894D1292DB; Sat, 24 Mar 2018 20:06:39 +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 DA4BE29272 for ; Sat, 24 Mar 2018 20:06:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753559AbeCXUGJ (ORCPT ); Sat, 24 Mar 2018 16:06:09 -0400 Received: from onstation.org ([52.200.56.107]:52986 "EHLO onstation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752913AbeCXUGG (ORCPT ); Sat, 24 Mar 2018 16:06:06 -0400 Received: from xilitla.hsd1.wv.comcast.net (c-98-236-77-125.hsd1.wv.comcast.net [98.236.77.125]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: masneyb) by onstation.org (Postfix) with ESMTPSA id A610D3E3; Sat, 24 Mar 2018 20:06:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=onstation.org; s=default; t=1521921965; bh=YYn1tJt8I7l0Tv8yvfREEfW7TatKBkUuCSjgwZwbAjs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dntZyB77v2kJBpkjgzdrc89IsztwTgd7PBjCYYQGQll1CMuzQhQPO8/zu8tmJmHBR cHhbV9EwjiN6oQqUocbk+iw7eandiHj9k/bWtKbmYNHyBmMWK8ldE8XnjLAGRaZO4c XrIJMZK6CldvW1MB9aHw2U/7XCH34yEQV0EpGiNs= From: Brian Masney To: jic23@kernel.org, linux-iio@vger.kernel.org Cc: gregkh@linuxfoundation.org, devel@driverdev.osuosl.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, linux-kernel@vger.kernel.org, Jon.Brenner@ams.com Subject: [PATCH 1/4] staging: iio: tsl2x7x: use auto increment I2C protocol Date: Sat, 24 Mar 2018 16:05:52 -0400 Message-Id: <20180324200555.1403-2-masneyb@onstation.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180324200555.1403-1-masneyb@onstation.org> References: <20180324200555.1403-1-masneyb@onstation.org> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The hardware supports 16-bit ALS and proximity readings, however the datasheet recommends using the I2C auto increment protocol so that the correct high and low bytes are read even if the integration cycle ends between reading the lower and upper registers. More information about this protocol can be found at https://www.i2c-bus.org/auto-increment/. Signed-off-by: Brian Masney --- drivers/staging/iio/light/tsl2x7x.c | 100 ++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 33 deletions(-) diff --git a/drivers/staging/iio/light/tsl2x7x.c b/drivers/staging/iio/light/tsl2x7x.c index 77a81d75af4f..8530bccdb317 100644 --- a/drivers/staging/iio/light/tsl2x7x.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -80,6 +80,8 @@ /* tsl2X7X cmd reg masks */ #define TSL2X7X_CMD_REG 0x80 #define TSL2X7X_CMD_SPL_FN 0x60 +#define TSL2X7X_CMD_REPEAT_PROTO 0x00 +#define TSL2X7X_CMD_AUTOINC_PROTO 0x20 #define TSL2X7X_CMD_PROX_INT_CLR 0X05 #define TSL2X7X_CMD_ALS_INT_CLR 0x06 @@ -320,6 +322,55 @@ static int tsl2x7x_write_control_reg(struct tsl2X7X_chip *chip, u8 data) return ret; } +static int tsl2x7x_read_autoinc_regs(struct tsl2X7X_chip *chip, int lower_reg, + int upper_reg) +{ + u8 buf[2]; + int ret; + + ret = i2c_smbus_write_byte(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CMD_AUTOINC_PROTO | + lower_reg); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to enable auto increment protocol: %d\n", + __func__, ret); + return ret; + } + + ret = i2c_smbus_read_byte_data(chip->client, + TSL2X7X_CMD_REG | lower_reg); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to read from register %x: %d\n", __func__, + lower_reg, ret); + return ret; + } + buf[0] = ret; + + ret = i2c_smbus_read_byte_data(chip->client, + TSL2X7X_CMD_REG | upper_reg); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to read from register %x: %d\n", __func__, + upper_reg, ret); + return ret; + } + buf[1] = ret; + + ret = i2c_smbus_write_byte(chip->client, + TSL2X7X_CMD_REG | TSL2X7X_CMD_REPEAT_PROTO | + lower_reg); + if (ret < 0) { + dev_err(&chip->client->dev, + "%s: failed to enable repeated byte protocol: %d\n", + __func__, ret); + return ret; + } + + return le16_to_cpup((const __le16 *)&buf[0]); +} + /** * tsl2x7x_get_lux() - Reads and calculates current lux value. * @indio_dev: pointer to IIO device @@ -340,9 +391,8 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) struct tsl2X7X_chip *chip = iio_priv(indio_dev); struct tsl2x7x_lux *p; u32 lux, ratio; - int i, ret; u64 lux64; - u8 buf[4]; + int ret; mutex_lock(&chip->als_mutex); @@ -366,23 +416,17 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) goto out_unlock; } - for (i = 0; i < 4; i++) { - int reg = TSL2X7X_CMD_REG | (TSL2X7X_ALS_CHAN0LO + i); - - ret = i2c_smbus_read_byte_data(chip->client, reg); - if (ret < 0) { - dev_err(&chip->client->dev, - "%s: failed to read from register %x: %d\n", - __func__, reg, ret); - goto out_unlock; - } - - buf[i] = ret; - } + ret = tsl2x7x_read_autoinc_regs(chip, TSL2X7X_ALS_CHAN0LO, + TSL2X7X_ALS_CHAN0HI); + if (ret < 0) + goto out_unlock; + chip->als_cur_info.als_ch0 = ret; - /* extract ALS/lux data */ - chip->als_cur_info.als_ch0 = le16_to_cpup((const __le16 *)&buf[0]); - chip->als_cur_info.als_ch1 = le16_to_cpup((const __le16 *)&buf[2]); + ret = tsl2x7x_read_autoinc_regs(chip, TSL2X7X_ALS_CHAN1LO, + TSL2X7X_ALS_CHAN1HI); + if (ret < 0) + goto out_unlock; + chip->als_cur_info.als_ch1 = ret; if (chip->als_cur_info.als_ch0 >= chip->als_saturation || chip->als_cur_info.als_ch1 >= chip->als_saturation) { @@ -456,10 +500,8 @@ static int tsl2x7x_get_lux(struct iio_dev *indio_dev) */ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) { - int i; - int ret; - u8 chdata[2]; struct tsl2X7X_chip *chip = iio_priv(indio_dev); + int ret; mutex_lock(&chip->prox_mutex); @@ -490,18 +532,10 @@ static int tsl2x7x_get_prox(struct iio_dev *indio_dev) break; } - for (i = 0; i < 2; i++) { - int reg = TSL2X7X_CMD_REG | (TSL2X7X_PRX_LO + i); - - ret = i2c_smbus_read_byte_data(chip->client, reg); - if (ret < 0) - goto prox_poll_err; - - chdata[i] = ret; - } - - chip->prox_data = le16_to_cpup((const __le16 *)&chdata[0]); - ret = chip->prox_data; + ret = tsl2x7x_read_autoinc_regs(chip, TSL2X7X_PRX_LO, TSL2X7X_PRX_HI); + if (ret < 0) + goto prox_poll_err; + chip->prox_data = ret; prox_poll_err: mutex_unlock(&chip->prox_mutex);