From patchwork Thu Oct 12 13:17:59 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maciej Purski X-Patchwork-Id: 10001915 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 D6F346028A for ; Thu, 12 Oct 2017 13:18:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C88E728DC1 for ; Thu, 12 Oct 2017 13:18:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BCA2828DC8; Thu, 12 Oct 2017 13:18:25 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 3752A28DC1 for ; Thu, 12 Oct 2017 13:18:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756105AbdJLNSV (ORCPT ); Thu, 12 Oct 2017 09:18:21 -0400 Received: from mailout2.w1.samsung.com ([210.118.77.12]:48506 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753350AbdJLNSS (ORCPT ); Thu, 12 Oct 2017 09:18:18 -0400 Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20171012131815euoutp02f3147f57c9ddc3ae4a1f50522ace380a~s1Rzrv-dQ3111431114euoutp022; Thu, 12 Oct 2017 13:18:15 +0000 (GMT) Received: from eusmges4.samsung.com (unknown [203.254.199.244]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20171012131814eucas1p1c34be187745f86d1f3037c9947dcba4a~s1RzCwkjW2629626296eucas1p19; Thu, 12 Oct 2017 13:18:14 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges4.samsung.com (EUCPMTA) with SMTP id 19.B9.12944.69B6FD95; Thu, 12 Oct 2017 14:18:14 +0100 (BST) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20171012131814eucas1p172faad38314e077e3395befaceef77af~s1RyXSy8f1351713517eucas1p1W; Thu, 12 Oct 2017 13:18:14 +0000 (GMT) X-AuditID: cbfec7f4-f79ab6d000003290-1e-59df6b96473b Received: from eusync4.samsung.com ( [203.254.199.214]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id 6F.90.18832.59B6FD95; Thu, 12 Oct 2017 14:18:14 +0100 (BST) Received: from AMDC2075.DIGITAL.local ([106.120.51.25]) by eusync4.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OXP0071YOY5COB0@eusync4.samsung.com>; Thu, 12 Oct 2017 14:18:13 +0100 (BST) From: Maciej Purski To: devicetree@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-iio@vger.kernel.org Cc: Rob Herring , Mark Rutland , Guenter Roeck , Jean Delvare , Jonathan Corbet , Russell King , Kukjin Kim , Krzysztof Kozlowski , Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Bartlomiej Zolnierkiewicz , Marek Szyprowski , Maciej Purski Subject: [PATCH v3 1/4] iio: adc: ina2xx: Make max expected current configurable Date: Thu, 12 Oct 2017 15:17:59 +0200 Message-id: <1507814282-1486-2-git-send-email-m.purski@samsung.com> X-Mailer: git-send-email 2.7.4 In-reply-to: <1507814282-1486-1-git-send-email-m.purski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAAzVSa0hTYRj22zlnOw5nh6n1oSIxyEjTUiQ+sqLIH4dAqChB89LSg5pObVPx UrSKvP0w2/JCgRecmmJe5hQ1Jjqni9Sd5t1saWg/TKmGpUaa6Tb/Pe/7PO/z8MBLYkIV4U4m pqQz0hRxsojLx7uG/xj9ypIWwk/3WrxQe0UrgZb78wGq0hsJNFZyDS0+buKgZ0urGOrdXcMQ y7bxkEpZRSD10jSBavJUOMpf7QSoUv8dRxVsHwfpSrUALdeMclD1ykccvdGbeahuxsRBf3uH eeipVs+76EY3VzYDemLahNE/LdG0uqmQS3eoHtK1xUqCVq3pCJp9ogd0z6acRxdrmgDdqpnC 6XW111WnCP65OCY5MZORnrpwm5+wa+wk0gxnstbb9YQctPgWAUcSUkHwPbvNseHD8MPnVm4R 4JNCqg7AQbPZPqwDqC4d4R5cPG/YATaiHsCxzTHMNuwCyL417TEkyaV8YHN+zP7eleoDcGJr 3GqFUSwO67Vl2L6VC3Ud1vz4ZA3HqWNw1KKwYgF1GbZ372C2OC84ZyzE9k0dqRBoUaB9H0i1 8OC7jVm7JgR2flnBbdgFfjNoeDbsCQsLBuzlcqHpd6+9wn34aL7NrgmG6wqN1QejnKGiq9ya BSkBLMgT2iQ0bNtotMsvwcmtRtxWuBzAOXMXtwR4VAOHJuDKZMgk8YwsyF8mlsgyUuL9Y1Ml arD3OyP/DL+6Qe3wWR2gSCByEiDeQriQEGfKsiU6AElM5CoITdhbCeLE2TmMNDVGmpHMyHTA g8RFRwTnI/LChVS8OJ1JYpg0RnrAckhHdznQmIL5Fsrbpz/u62Ss4lX20LjmXsZMx9Z2emng 3ZkorX6I3DSyiREDPQN3WInZxS3HsMF1ng/MKVi4EZ3+umFcWXJo4EHpUNS0efnFSfblidmp zcistdBIZbBZK1paLpKrPY/7KYRtvrkmB+8O+eBKmCHs1tE81ytK7c2A8EURLksQB/hgUpn4 P3zar5U3AwAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrBLMWRmVeSWpSXmKPExsVy+t/xa7rTsu9HGiyzsNg4Yz2rxZMD7YwW 84+cY7U4OyHQ4kHTKiaL/sevmS12/X/DbHH+/AZ2iyWT57NabHp8jdViYdsSFov211sZLeYd ecdiMeP8PiaLQ1P3Mlo8WXiGyWLBy1ssFmuP3GW3WHr9IpPF713H2C1a9x5hdxD1WDNvDaPH 5WsXmT0+fIzz2LSqk81j85J6j8V9k1k9lrw5xOpxvvkIo8fO7w3sHn1bVjF6rN9ylcXj8ya5 AJ4oLpuU1JzMstQifbsEroz/57ayFhw3q/i88QhrA+M67S5GTg4JAROJicv/MkLYYhIX7q1n 62Lk4hASWMIocfL7BXYIp5FJ4vXPNpYuRg4ONgEtiTXt8SBxEYF9jBKnH89lBHGYBS6ySJzZ s44FZJSwQIDEnP/3mEBsFgFViTMfJ4HZvALOEht3/GWGWCcncfNcJzPIUE4BF4mPkyxAwkJA JW2PO1gnMPIuYGRYxSiSWlqcm55bbKhXnJhbXJqXrpecn7uJERgf24793LyD8dLG4EOMAhyM Sjy8N/7eixRiTSwrrsw9xCjBwawkwuubcT9SiDclsbIqtSg/vqg0J7X4EKM0B4uSOG/vntWR QgLpiSWp2ampBalFMFkmDk6pBsbaC+ca452bv9wMfXqAZZnrZp+vB5ODJ9Rw86k2TvlxcOWt 137lE/Rb8/Rb13ZY3+VjWXn4zmuJPo4ImVPrrh1d3ppv/tCPYfaq0j+H48T65AS/zPvW/TSi 5sqWqLi13bnnHM6He4n6Myw6rHmZhZddwW7GlkebQj/fPPDw3PcFxdrXYvXrZmQqsRRnJBpq MRcVJwIA87SswosCAAA= X-CMS-MailID: 20171012131814eucas1p172faad38314e077e3395befaceef77af X-Msg-Generator: CA X-Sender-IP: 182.198.249.179 X-Local-Sender: =?UTF-8?B?TWFjaWVqIFB1cnNraRtTZWN1cml0eSAoVFApG1NhbXN1bmcg?= =?UTF-8?B?RWxlY3Ryb25pY3MbVHJhaW5lZSAoKQ==?= X-Global-Sender: =?UTF-8?B?TWFjaWVqIFB1cnNraRtTZWN1cml0eSAoVFApG1NhbXN1bmcg?= =?UTF-8?B?RWxlY3Ryb25pY3MbVHJhaW5lZSAoKQ==?= X-Sender-Code: =?UTF-8?B?QzEwG0VIURtDMTBDRDAyQ0QwMjczOTU=?= CMS-TYPE: 201P X-CMS-RootMailID: 20171012131814eucas1p172faad38314e077e3395befaceef77af X-RootMTR: 20171012131814eucas1p172faad38314e077e3395befaceef77af References: <1507814282-1486-1-git-send-email-m.purski@samsung.com> 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 Max expected current is used for calculating calibration register value, Current LSB and Power LSB according to equations found in ina datasheet: current_lsb = max_expected_current / 2^15 calibration_register = 0.00512 / (current_lsb * r_shunt) power_lsb = 25 * current_lsb (for ina231, 230, 226) power_lsb = 20 * current_lsb (for older ones) Max expected current is now implicitly set to default value, which is 2^15, thanks to which Current LSB is equal to 1 mA and Power LSB is equal to 20000 uW or 25000 uW depending on ina model, but users have no impact on the precision of the device. Make max expected current configurable from device tree or platform_data. Allow changing current_lsb from sysfs. It is exposed in sysfs as scale attribute for IIO current channel. Update calibration register and power_lsb value on each scale change. Signed-off-by: Maciej Purski --- drivers/iio/adc/ina2xx-adc.c | 96 ++++++++++++++++++++++++++---------- include/linux/platform_data/ina2xx.h | 2 + 2 files changed, 73 insertions(+), 25 deletions(-) diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index a16f8c6..be26dfc 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -56,6 +56,7 @@ #define INA226_DEFAULT_IT 1110 #define INA2XX_RSHUNT_DEFAULT 10000 +#define INA2XX_MAX_EXPECTED_MA_DEFAULT BIT(15) /* current_lsb = 1 mA */ /* * bit masks for reading the settings in the configuration register @@ -114,7 +115,7 @@ struct ina2xx_config { int shunt_div; int bus_voltage_shift; int bus_voltage_lsb; /* uV */ - int power_lsb; /* uW */ + int power_lsb_factor; enum ina2xx_ids chip_id; }; @@ -123,7 +124,9 @@ struct ina2xx_chip_info { struct task_struct *task; const struct ina2xx_config *config; struct mutex state_lock; - unsigned int shunt_resistor; + unsigned int shunt_resistor; /* uOhms */ + int current_lsb; /* uA */ + int power_lsb; /* uW */ int avg; int int_time_vbus; /* Bus voltage integration time uS */ int int_time_vshunt; /* Shunt voltage integration time uS */ @@ -137,7 +140,7 @@ static const struct ina2xx_config ina2xx_config[] = { .shunt_div = 100, .bus_voltage_shift = 3, .bus_voltage_lsb = 4000, - .power_lsb = 20000, + .power_lsb_factor = 20, .chip_id = ina219, }, [ina226] = { @@ -146,7 +149,7 @@ static const struct ina2xx_config ina2xx_config[] = { .shunt_div = 400, .bus_voltage_shift = 0, .bus_voltage_lsb = 1250, - .power_lsb = 25000, + .power_lsb_factor = 25, .chip_id = ina226, }, }; @@ -210,14 +213,15 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev, case INA2XX_POWER: /* processed (mW) = raw*lsb (uW) / 1000 */ - *val = chip->config->power_lsb; + *val = chip->power_lsb; *val2 = 1000; return IIO_VAL_FRACTIONAL; case INA2XX_CURRENT: - /* processed (mA) = raw (mA) */ - *val = 1; - return IIO_VAL_INT; + /* processed (mA) = raw*lsb (uA) / 1000 */ + *val = chip->current_lsb; + *val2 = 1000; + return IIO_VAL_FRACTIONAL; } } @@ -353,6 +357,36 @@ static int ina219_set_int_time_vshunt(struct ina2xx_chip_info *chip, return 0; } +/* + * Calculate calibration value according to equation 1 in ina226 datasheet + * http://www.ti.com/lit/ds/symlink/ina226.pdf. + * Current LSB is in uA and RShunt is in uOhms, so RShunt should be + * converted to mOhms in order to keep the scale. + * There is no need to expose the CALIBRATION register + * to the user for now. But we need to reset this register + * if the user updates RShunt or max expected current after driver + * init, e.g upon reading an EEPROM/Probe-type value. + */ +static int ina2xx_set_calibration(struct ina2xx_chip_info *chip) +{ + unsigned int rshunt = DIV_ROUND_CLOSEST(chip->shunt_resistor, 1000); + u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor, + chip->current_lsb * rshunt); + + return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval); +} + +static int ina2xx_set_scale(struct ina2xx_chip_info *chip, unsigned int val) +{ + if (val <= 0 || val > chip->config->calibration_factor) + return -EINVAL; + + chip->current_lsb = val; + chip->power_lsb = chip->current_lsb * chip->config->power_lsb_factor; + + return 0; +} + static int ina2xx_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) @@ -394,7 +428,18 @@ static int ina2xx_write_raw(struct iio_dev *indio_dev, &tmp); } break; - + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_CURRENT: + val = val * 1000 + DIV_ROUND_CLOSEST(val2, 1000); + ret = ina2xx_set_scale(chip, val); + if (!ret) + ret = ina2xx_set_calibration(chip); + break; + default: + ret = -EINVAL; + } + break; default: ret = -EINVAL; } @@ -433,22 +478,6 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev, return len; } -/* - * Set current LSB to 1mA, shunt is in uOhms - * (equation 13 in datasheet). We hardcode a Current_LSB - * of 1.0 x10-6. The only remaining parameter is RShunt. - * There is no need to expose the CALIBRATION register - * to the user for now. But we need to reset this register - * if the user updates RShunt after driver init, e.g upon - * reading an EEPROM/Probe-type value. - */ -static int ina2xx_set_calibration(struct ina2xx_chip_info *chip) -{ - u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor, - chip->shunt_resistor); - - return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval); -} static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val) { @@ -849,6 +878,23 @@ static int ina2xx_probe(struct i2c_client *client, if (ret) return ret; + if (of_property_read_u32(client->dev.of_node, + "ti-max-expected-current-milliamp", &val) < 0) { + struct ina2xx_platform_data *pdata = + dev_get_platdata(&client->dev); + + if (pdata && pdata->max_mA != 0) + val = pdata->max_mA; + else + val = INA2XX_MAX_EXPECTED_MA_DEFAULT; + } + + /* Calculate current_lsb: max-expected-current / 2^15 */ + val = DIV_ROUND_CLOSEST(val * 1000, (1 << 15)); + ret = ina2xx_set_scale(chip, val); + if (ret) + return ret; + /* Patch the current config register with default. */ val = chip->config->config_default; diff --git a/include/linux/platform_data/ina2xx.h b/include/linux/platform_data/ina2xx.h index 9abc0ca..f02b1d8 100644 --- a/include/linux/platform_data/ina2xx.h +++ b/include/linux/platform_data/ina2xx.h @@ -13,7 +13,9 @@ /** * struct ina2xx_platform_data - ina2xx info * @shunt_uohms shunt resistance in microohms + * @max_mA max expected current in mA */ struct ina2xx_platform_data { long shunt_uohms; + int max_mA; };