From patchwork Thu Oct 12 12:36:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maciej Purski X-Patchwork-Id: 10001823 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 36C106028A for ; Thu, 12 Oct 2017 12:36:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 28F7628DAE for ; Thu, 12 Oct 2017 12:36:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1D4E428DB6; Thu, 12 Oct 2017 12:36:40 +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=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 1F66128DAE for ; Thu, 12 Oct 2017 12:36:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752800AbdJLMgi (ORCPT ); Thu, 12 Oct 2017 08:36:38 -0400 Received: from mailout1.w1.samsung.com ([210.118.77.11]:51760 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752581AbdJLMgf (ORCPT ); Thu, 12 Oct 2017 08:36:35 -0400 Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout1.w1.samsung.com (KnoxPortal) with ESMTP id 20171012123633euoutp016e0cc9e733c8d86617ea807210ce1fc4~s0tZvq0w23176931769euoutp01h; Thu, 12 Oct 2017 12:36:33 +0000 (GMT) Received: from eusmges5.samsung.com (unknown [203.254.199.245]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20171012123632eucas1p2442a191641ac50ce355a03ba7c6f7cbf~s0tY-cXGf0059500595eucas1p2-; Thu, 12 Oct 2017 12:36:32 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges5.samsung.com (EUCPMTA) with SMTP id B7.0B.12743.0D16FD95; Thu, 12 Oct 2017 13:36:32 +0100 (BST) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20171012123632eucas1p1638754631a455ec6ff5f9770f6c33a95~s0tYWDPdC0133301333eucas1p13; Thu, 12 Oct 2017 12:36:32 +0000 (GMT) X-AuditID: cbfec7f5-f79d06d0000031c7-ae-59df61d05805 Received: from eusync4.samsung.com ( [203.254.199.214]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id 90.5A.18832.0D16FD95; Thu, 12 Oct 2017 13:36:32 +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 <0OXP00DU9N0HRK20@eusync4.samsung.com>; Thu, 12 Oct 2017 13:36:32 +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 v2 1/4] iio: adc: ina2xx: Make max expected current configurable Date: Thu, 12 Oct 2017 14:36:02 +0200 Message-id: <1507811765-31005-2-git-send-email-m.purski@samsung.com> X-Mailer: git-send-email 2.7.4 In-reply-to: <1507811765-31005-1-git-send-email-m.purski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAAz2SfSzUcRzH+/4e7vdD1353qG9Rq2s2U6iRvpWsVq1frenpj3Zarl/8wvLU HUZZ0QPRdEJ1tXYoqt0uT12SRToXU5fzEEbERg+ewsz0sJLzU/+99v68H/bdvjQuzSOX0WGR MbwykguXiWyJ8rofje5NXK983fUBF1SqKSbRQE0qQLmmRhK9yzyI+i7oMKTuH8ZR5cwIjiyW EgoVZOeSqKy/nUT5KQUESh1+CpDW9I1AGks1how3qgAayDdjKG+wi0CPTT0UKuxoxtCvyjoK Xa4yUdscWb1WD9jW9macHZ8IZMt0aSL2ScF59v61bJItGDGSrOWiCbDPp5Mo9ppBB9hiQxvB TpatOLAwwNY3mA8Pi+OVnn7HbUPHan2i633ix+pGsSRQtCYd2NCQ8YaDnWpc4MWw6WOxKB3Y 0lKmEECtehqzHqTMJICDlh3/A/dy5/UHs6aHx4TADIBTXW0gHdC0iHGD+lSFVXdgqgFs/d4y 14ozFgI+qLo5N2fPHILq0WeElQnGBY52XKWsLGZ2QsvvaUJYWwE7G9Pm/DbMLvjo/gfSWgSZ IgoW5agp6xqcDQzqjgh+ezhUb6AEdoZpV15hAp+FzVOVIoETYfKHknnPFjiZZZjrx5lFMKv8 Fi5UiuGVFKlgYWFpT+58dDvMef8GCI/XAKjLXpsJnPLAAh1w4GNVESG8aoOHiotQxUaGeARF RZSB2X/z9k/9VAUorNtsBAwNZAvFX+165VKSi1MlRBgBpHGZg9gSOCuJg7mEM7wySqGMDedV RuBEE7Il4q0BKXIpE8LF8Kd4PppX/rtitM2yJNB9bql5KOFLdUOTxL/CfVx212v88KXVpowW R187V5u920JckmtcbytOep9f7vGyPIYK4vSE2WBvh3meiM+TeHb8/OMs6Tq836tr1TAs/aT1 vqOr36StlfT9jGvwMxQdnNmz7/NK/19H7Tea1Q9fm3WJ3At5S8bufE25XDJxukPRLSNUodx6 N1yp4v4CFhECIjMDAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrJLMWRmVeSWpSXmKPExsVy+t/xa7oXEu9HGlycyGWxccZ6VosnB9oZ LeYfOcdqcXZCoMWDplVMFv2PXzNb7Pr/htni/PkN7BZLJs9ntdj0+BqrxcK2JSwW7a+3MlrM O/KOxWLG+X1MFoem7mW0eLLwDJPFgpe3WCzWHrnLbrH0+kUmi9+7jrFbtO49wu4g6rFm3hpG j8vXLjJ7fPgY57FpVSebx+Yl9R6L+yazeix5c4jV43zzEUaPnd8b2D36tqxi9Fi/5SqLx+dN cgE8UVw2Kak5mWWpRfp2CVwZ7w+bFRw3q3h/7C1TA+M67S5GTg4JAROJl4vmM0HYYhIX7q1n 62Lk4hASWMIoMX/tQyYIp5FJ4ujFXqAMBwebgJbEmvZ4kLiIwD5GidOP5zKCOMwCF1kkzuxZ xwIySlggQGJB62VWEJtFQFXi7fVudhCbV8BF4vzf7ywQ6+Qkbp7rZAaxOQVcJVYsvg1WLwRU 03pxLeMERt4FjAyrGEVSS4tz03OLDfWKE3OLS/PS9ZLzczcxAiNk27Gfm3cwXtoYfIhRgINR iYf3xt97kUKsiWXFlbmHGCU4mJVEeM/H3Y8U4k1JrKxKLcqPLyrNSS0+xCjNwaIkztu7Z3Wk kEB6YklqdmpqQWoRTJaJg1OqgVGz7brbSYs2w09TU/g/38tQSWDdkPLI9vxXxcfz0mNltRd5 qy39czt3nmOIuev9Od9LRArOFOuu8dl7co1E9Y/fN3//YHeIff7mjr2c1hy3tB879E5//qxy Vufc5IK0rC9iu49PqBersPuYsfnKG9YC5x0XdSPf29rMPzth7q7v0qeDaj2Xr/+jxFKckWio xVxUnAgAgswjBowCAAA= X-CMS-MailID: 20171012123632eucas1p1638754631a455ec6ff5f9770f6c33a95 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: 20171012123632eucas1p1638754631a455ec6ff5f9770f6c33a95 X-RootMTR: 20171012123632eucas1p1638754631a455ec6ff5f9770f6c33a95 References: <1507811765-31005-1-git-send-email-m.purski@samsung.com> Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@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..7f1ae79 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-microamp", &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; };