aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Wunner2017-08-22 08:33:00 -0500
committerGreg Kroah-Hartman2017-10-12 04:27:34 -0500
commit18215da0c24117da53b164467b89f5dc350b4d0b (patch)
tree363a5f9ff0ce805f9a606b7257e7b5f0eb7e73a5
parentf2f68ec0b2847b38d5d0dcb64470a45d9c96edf7 (diff)
downloadti-linux-kernel-18215da0c24117da53b164467b89f5dc350b4d0b.tar.gz
ti-linux-kernel-18215da0c24117da53b164467b89f5dc350b4d0b.tar.xz
ti-linux-kernel-18215da0c24117da53b164467b89f5dc350b4d0b.zip
iio: adc: mcp320x: Fix readout of negative voltages
commit e6f4794371ee7cce1339e7ca9542f1e703c5f84a upstream. Commit f686a36b4b79 ("iio: adc: mcp320x: Add support for mcp3301") returns a signed voltage from mcp320x_adc_conversion() but neglects that the caller interprets a negative return value as failure. Only mcp3301 (and the upcoming mcp3550/1/3) is affected as the other chips are incapable of measuring negative voltages. Fix and while at it, add mcp3301 to the list of supported chips at the top of the file. Fixes: f686a36b4b79 ("iio: adc: mcp320x: Add support for mcp3301") Cc: Andrea Galbusera <gizero@gmail.com> Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/iio/adc/mcp320x.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index 8569c8e1f4b2..5c51f6f5cbff 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -17,6 +17,8 @@
17 * MCP3204 17 * MCP3204
18 * MCP3208 18 * MCP3208
19 * ------------ 19 * ------------
20 * 13 bit converter
21 * MCP3301
20 * 22 *
21 * Datasheet can be found here: 23 * Datasheet can be found here:
22 * http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001 24 * http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001
@@ -96,7 +98,7 @@ static int mcp320x_channel_to_tx_data(int device_index,
96} 98}
97 99
98static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, 100static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
99 bool differential, int device_index) 101 bool differential, int device_index, int *val)
100{ 102{
101 int ret; 103 int ret;
102 104
@@ -117,19 +119,25 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
117 119
118 switch (device_index) { 120 switch (device_index) {
119 case mcp3001: 121 case mcp3001:
120 return (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3); 122 *val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3);
123 return 0;
121 case mcp3002: 124 case mcp3002:
122 case mcp3004: 125 case mcp3004:
123 case mcp3008: 126 case mcp3008:
124 return (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6); 127 *val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6);
128 return 0;
125 case mcp3201: 129 case mcp3201:
126 return (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1); 130 *val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1);
131 return 0;
127 case mcp3202: 132 case mcp3202:
128 case mcp3204: 133 case mcp3204:
129 case mcp3208: 134 case mcp3208:
130 return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4); 135 *val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
136 return 0;
131 case mcp3301: 137 case mcp3301:
132 return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12); 138 *val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8
139 | adc->rx_buf[1], 12);
140 return 0;
133 default: 141 default:
134 return -EINVAL; 142 return -EINVAL;
135 } 143 }
@@ -150,12 +158,10 @@ static int mcp320x_read_raw(struct iio_dev *indio_dev,
150 switch (mask) { 158 switch (mask) {
151 case IIO_CHAN_INFO_RAW: 159 case IIO_CHAN_INFO_RAW:
152 ret = mcp320x_adc_conversion(adc, channel->address, 160 ret = mcp320x_adc_conversion(adc, channel->address,
153 channel->differential, device_index); 161 channel->differential, device_index, val);
154
155 if (ret < 0) 162 if (ret < 0)
156 goto out; 163 goto out;
157 164
158 *val = ret;
159 ret = IIO_VAL_INT; 165 ret = IIO_VAL_INT;
160 break; 166 break;
161 167