Commit eb3e6ae9 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-3.13c' of...

Merge tag 'iio-for-3.13c' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

Third set of new functionality and cleanups for IIO in the 3.13 cycle.

Driver New Functionality
* MXS - new interrupt driven touch screen support for i.MX23/28. Old
  polled implementation dropped.

Driver Cleanups
* Some spi_sync boilerplate dropped by using spi_sync_transfer
* Some switching of drivers to the fractional type for scale reading.
  Moves the ugly calculation into one place.
* Fix the documentation for *_voltage_scale which is never been correct
  or as implemented in any driver.
* HID sensor hub and children : Open the sensor hub only when someone cares.
* hmc5843 - various minor
parents 5f1a1369 3658a71b
......@@ -79,7 +79,7 @@ Description:
correspond to externally available input one of the named
versions may be used. The number must always be specified and
unique to allow association with event codes. Units after
application of scale and offset are microvolts.
application of scale and offset are millivolts.
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw
KernelVersion: 2.6.35
......@@ -90,7 +90,7 @@ Description:
physically equivalent inputs when non differential readings are
separately available. In differential only parts, then all that
is required is a consistent labeling. Units after application
of scale and offset are microvolts.
of scale and offset are millivolts.
What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw
KernelVersion: 3.2
......
* Freescale i.MX28 LRADC device driver
Required properties:
- compatible: Should be "fsl,imx28-lradc"
- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
for i.MX28 SoC
- reg: Address and length of the register set for the device
- interrupts: Should contain the LRADC interrupts
......@@ -9,13 +10,38 @@ Optional properties:
- fsl,lradc-touchscreen-wires: Number of wires used to connect the touchscreen
to LRADC. Valid value is either 4 or 5. If this
property is not present, then the touchscreen is
disabled.
disabled. 5 wires is valid for i.MX28 SoC only.
- fsl,ave-ctrl: number of samples per direction to calculate an average value.
Allowed value is 1 ... 31, default is 4
- fsl,ave-delay: delay between consecutive samples. Allowed value is
1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at
2 kHz and its default is 2 (= 1 ms)
- fsl,settling: delay between plate switch to next sample. Allowed value is
1 ... 2047. It counts at 2 kHz and its default is
10 (= 5 ms)
Examples:
Example for i.MX23 SoC:
lradc@80050000 {
compatible = "fsl,imx23-lradc";
reg = <0x80050000 0x2000>;
interrupts = <36 37 38 39 40 41 42 43 44>;
status = "okay";
fsl,lradc-touchscreen-wires = <4>;
fsl,ave-ctrl = <4>;
fsl,ave-delay = <2>;
fsl,settling = <10>;
};
Example for i.MX28 SoC:
lradc@80050000 {
compatible = "fsl,imx28-lradc";
reg = <0x80050000 0x2000>;
interrupts = <10 14 15 16 17 18 19
20 21 22 23 24 25>;
interrupts = <10 14 15 16 17 18 19 20 21 22 23 24 25>;
status = "okay";
fsl,lradc-touchscreen-wires = <5>;
fsl,ave-ctrl = <4>;
fsl,ave-delay = <2>;
fsl,settling = <10>;
};
......@@ -430,6 +430,7 @@ lradc@80050000 {
reg = <0x80050000 0x2000>;
interrupts = <36 37 38 39 40 41 42 43 44>;
status = "disabled";
clocks = <&clks 26>;
};
spdif@80054000 {
......
......@@ -183,6 +183,10 @@ saif1: saif@80046000 {
lradc@80050000 {
status = "okay";
fsl,lradc-touchscreen-wires = <4>;
fsl,ave-ctrl = <4>;
fsl,ave-delay = <2>;
fsl,settling = <10>;
};
i2c0: i2c@80058000 {
......
......@@ -902,6 +902,7 @@ lradc: lradc@80050000 {
interrupts = <10 14 15 16 17 18 19
20 21 22 23 24 25>;
status = "disabled";
clocks = <&clks 41>;
};
spdif: spdif@80054000 {
......
......@@ -465,6 +465,39 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
return 1;
}
int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev)
{
int ret = 0;
struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
mutex_lock(&data->mutex);
if (!hsdev->ref_cnt) {
ret = hid_hw_open(hsdev->hdev);
if (ret) {
hid_err(hsdev->hdev, "failed to open hid device\n");
mutex_unlock(&data->mutex);
return ret;
}
}
hsdev->ref_cnt++;
mutex_unlock(&data->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(sensor_hub_device_open);
void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev)
{
struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
mutex_lock(&data->mutex);
hsdev->ref_cnt--;
if (!hsdev->ref_cnt)
hid_hw_close(hsdev->hdev);
mutex_unlock(&data->mutex);
}
EXPORT_SYMBOL_GPL(sensor_hub_device_close);
static int sensor_hub_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
......@@ -506,12 +539,6 @@ static int sensor_hub_probe(struct hid_device *hdev,
hid_err(hdev, "hw start failed\n");
return ret;
}
ret = hid_hw_open(hdev);
if (ret) {
hid_err(hdev, "failed to open input interrupt pipe\n");
goto err_stop_hw;
}
INIT_LIST_HEAD(&sd->dyn_callback_list);
sd->hid_sensor_client_cnt = 0;
report_enum = &hdev->report_enum[HID_INPUT_REPORT];
......@@ -520,7 +547,7 @@ static int sensor_hub_probe(struct hid_device *hdev,
if (dev_cnt > HID_MAX_PHY_DEVICES) {
hid_err(hdev, "Invalid Physical device count\n");
ret = -EINVAL;
goto err_close;
goto err_stop_hw;
}
sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt *
sizeof(struct mfd_cell),
......@@ -528,7 +555,7 @@ static int sensor_hub_probe(struct hid_device *hdev,
if (sd->hid_sensor_hub_client_devs == NULL) {
hid_err(hdev, "Failed to allocate memory for mfd cells\n");
ret = -ENOMEM;
goto err_close;
goto err_stop_hw;
}
list_for_each_entry(report, &report_enum->report_list, list) {
hid_dbg(hdev, "Report id:%x\n", report->id);
......@@ -565,8 +592,6 @@ static int sensor_hub_probe(struct hid_device *hdev,
for (i = 0; i < sd->hid_sensor_client_cnt ; ++i)
kfree(sd->hid_sensor_hub_client_devs[i].name);
kfree(sd->hid_sensor_hub_client_devs);
err_close:
hid_hw_close(hdev);
err_stop_hw:
hid_hw_stop(hdev);
......
......@@ -27,7 +27,7 @@
struct ad7266_state {
struct spi_device *spi;
struct regulator *reg;
unsigned long vref_uv;
unsigned long vref_mv;
struct spi_transfer single_xfer[3];
struct spi_message single_msg;
......@@ -156,7 +156,7 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long m)
{
struct ad7266_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
unsigned long scale_mv;
int ret;
switch (m) {
......@@ -174,16 +174,15 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_uv * 100);
scale_mv = st->vref_mv;
if (st->mode == AD7266_MODE_DIFF)
scale_uv *= 2;
scale_mv *= 2;
if (st->range == AD7266_RANGE_2VREF)
scale_uv *= 2;
scale_mv *= 2;
scale_uv >>= chan->scan_type.realbits;
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
*val = scale_mv;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
if (st->range == AD7266_RANGE_2VREF &&
st->mode != AD7266_MODE_DIFF)
......@@ -414,10 +413,10 @@ static int ad7266_probe(struct spi_device *spi)
if (ret < 0)
goto error_disable_reg;
st->vref_uv = ret;
st->vref_mv = ret / 1000;
} else {
/* Use internal reference */
st->vref_uv = 2500000;
st->vref_mv = 2500;
}
if (pdata) {
......
......@@ -127,10 +127,9 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
} else {
scale_uv = st->chip_info->int_vref_uv;
}
scale_uv >>= chan->scan_type.realbits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
......
......@@ -202,7 +202,6 @@ static int ad7791_read_raw(struct iio_dev *indio_dev,
{
struct ad7791_state *st = iio_priv(indio_dev);
bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR);
unsigned long long scale_pv;
switch (info) {
case IIO_CHAN_INFO_RAW:
......@@ -220,23 +219,26 @@ static int ad7791_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
/* The monitor channel uses an internal reference. */
if (chan->address == AD7791_CH_AVDD_MONITOR) {
scale_pv = 5850000000000ULL;
/*
* The signal is attenuated by a factor of 5 and
* compared against a 1.17V internal reference.
*/
*val = 1170 * 5;
} else {
int voltage_uv;
voltage_uv = regulator_get_voltage(st->reg);
if (voltage_uv < 0)
return voltage_uv;
scale_pv = (unsigned long long)voltage_uv * 1000000;
*val = voltage_uv / 1000;
}
if (unipolar)
scale_pv >>= chan->scan_type.realbits;
*val2 = chan->scan_type.realbits;
else
scale_pv >>= chan->scan_type.realbits - 1;
*val2 = do_div(scale_pv, 1000000000);
*val = scale_pv;
*val2 = chan->scan_type.realbits - 1;
return IIO_VAL_INT_PLUS_NANO;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
......
......@@ -366,9 +366,9 @@ static int at91_adc_read_raw(struct iio_dev *idev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = (st->vref_mv * 1000) >> chan->scan_type.realbits;
*val2 = 0;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->vref_mv;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
break;
}
......
......@@ -397,7 +397,6 @@ static int max1363_read_raw(struct iio_dev *indio_dev,
{
struct max1363_state *st = iio_priv(indio_dev);
int ret;
unsigned long scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
......@@ -406,10 +405,9 @@ static int max1363_read_raw(struct iio_dev *indio_dev,
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = st->vref_uv >> st->chip_info->bits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->vref_uv / 1000;
*val2 = st->chip_info->bits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
......
......@@ -34,6 +34,12 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
struct hid_sensor_common *st = iio_trigger_get_drvdata(trig);
int state_val;
if (state) {
if (sensor_hub_device_open(st->hsdev))
return -EIO;
} else
sensor_hub_device_close(st->hsdev);
state_val = state ? 1 : 0;
if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS))
++state_val;
......
......@@ -239,10 +239,9 @@ static int ad5064_read_raw(struct iio_dev *indio_dev,
if (scale_uv < 0)
return scale_uv;
scale_uv = (scale_uv * 100) >> chan->scan_type.realbits;
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
*val = scale_uv / 1000;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
break;
}
......
......@@ -379,15 +379,14 @@ static int ad5360_read_raw(struct iio_dev *indio_dev,
*val = ret >> chan->scan_type.shift;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/* vout = 4 * vref * dac_code */
scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100;
scale_uv = ad5360_get_channel_vref(st, chan->channel);
if (scale_uv < 0)
return scale_uv;
scale_uv >>= (chan->scan_type.realbits);
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
/* vout = 4 * vref * dac_code */
*val = scale_uv * 4 / 1000;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_CALIBBIAS:
ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET,
chan->address);
......
......@@ -204,7 +204,6 @@ static int ad5380_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info)
{
struct ad5380_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
int ret;
switch (info) {
......@@ -225,10 +224,9 @@ static int ad5380_read_raw(struct iio_dev *indio_dev,
val -= (1 << chan->scan_type.realbits) / 2;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = ((2 * st->vref) >> chan->scan_type.realbits) * 100;
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
*val = 2 * st->vref;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
break;
}
......@@ -271,72 +269,72 @@ static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
[ID_AD5380_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 40,
.int_vref = 1250000,
.int_vref = 1250,
},
[ID_AD5380_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 40,
.int_vref = 2500000,
.int_vref = 2500,
},
[ID_AD5381_3] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 1250000,
.int_vref = 1250,
},
[ID_AD5381_5] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 2500000,
.int_vref = 2500,
},
[ID_AD5382_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 32,
.int_vref = 1250000,
.int_vref = 1250,
},
[ID_AD5382_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 32,
.int_vref = 2500000,
.int_vref = 2500,
},
[ID_AD5383_3] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 32,
.int_vref = 1250000,
.int_vref = 1250,
},
[ID_AD5383_5] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 32,
.int_vref = 2500000,
.int_vref = 2500,
},
[ID_AD5390_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 16,
.int_vref = 1250000,
.int_vref = 1250,
},
[ID_AD5390_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 16,
.int_vref = 2500000,
.int_vref = 2500,
},
[ID_AD5391_3] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 1250000,
.int_vref = 1250,
},
[ID_AD5391_5] = {
.channel_template = AD5380_CHANNEL(12),
.num_channels = 16,
.int_vref = 2500000,
.int_vref = 2500,
},
[ID_AD5392_3] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 8,
.int_vref = 1250000,
.int_vref = 1250,
},
[ID_AD5392_5] = {
.channel_template = AD5380_CHANNEL(14),
.num_channels = 8,
.int_vref = 2500000,
.int_vref = 2500,
},
};
......@@ -395,7 +393,7 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
return ret;
}
if (st->chip_info->int_vref == 2500000)
if (st->chip_info->int_vref == 2500)
ctrl |= AD5380_CTRL_INT_VREF_2V5;
st->vref_reg = devm_regulator_get(dev, "vref");
......@@ -411,7 +409,7 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
if (ret < 0)
goto error_disable_reg;
st->vref = ret;
st->vref = ret / 1000;
} else {
st->vref = st->chip_info->int_vref;
ctrl |= AD5380_CTRL_INT_VREF_EN;
......
......@@ -281,18 +281,11 @@ static inline unsigned int ad5421_get_offset(struct ad5421_state *st)
return (min * (1 << 16)) / (max - min);
}
static inline unsigned int ad5421_get_scale(struct ad5421_state *st)
{
unsigned int min, max;
ad5421_get_current_min_max(st, &min, &max);
return ((max - min) * 1000) / (1 << 16);
}
static int ad5421_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long m)
{
struct ad5421_state *st = iio_priv(indio_dev);
unsigned int min, max;
int ret;
if (chan->type != IIO_CURRENT)
......@@ -306,9 +299,10 @@ static int ad5421_read_raw(struct iio_dev *indio_dev,
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = ad5421_get_scale(st);
return IIO_VAL_INT_PLUS_MICRO;
ad5421_get_current_min_max(st, &min, &max);
*val = max - min;
*val2 = (1 << 16) * 1000;
return IIO_VAL_FRACTIONAL;
case IIO_CHAN_INFO_OFFSET:
*val = ad5421_get_offset(st);
return IIO_VAL_INT;
......
......@@ -163,18 +163,15 @@ static int ad5446_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad5446_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
*val = st->cached_val;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->vref_mv;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
......
......@@ -101,7 +101,6 @@ static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
{
struct ad5449 *st = iio_priv(indio_dev);
int ret;
struct spi_message msg;
struct spi_transfer t[] = {
{
.tx_buf = &st->data[0],
......@@ -114,15 +113,11 @@ static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
},
};
spi_message_init(&msg);
spi_message_add_tail(&t[0], &msg);
spi_message_add_tail(&t[1], &msg);
mutex_lock(&indio_dev->mlock);
st->data[0] = cpu_to_be16(addr << 12);
st->data[1] = cpu_to_be16(AD5449_CMD_NOOP);
ret = spi_sync(st->spi, &msg);
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
if (ret < 0)
goto out_unlock;
......
......@@ -100,7 +100,6 @@ static int ad5504_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad5504_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
int ret;
switch (m) {
......@@ -113,11 +112,9 @@ static int ad5504_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->vref_mv;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
......
......@@ -50,15 +50,12 @@ static int ad5624r_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad5624r_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
switch (m) {
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->vref_mv;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
......
......@@ -201,7 +201,6 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad5686_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
int ret;
switch (m) {
......@@ -214,12 +213,9 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_mv * 100000)
>> (chan->scan_type.realbits);
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->vref_mv;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
......
......@@ -253,15 +253,6 @@ static inline int ad5755_get_offset(struct ad5755_state *st,
return (min * (1 << chan->scan_type.realbits)) / (max - min);
}
static inline int ad5755_get_scale(struct ad5755_state *st,
struct iio_chan_spec const *chan)
{
int min, max;
ad5755_get_min_max(st, chan, &min, &max);
return ((max - min) * 1000000000ULL) >> chan->scan_type.realbits;
}
static int ad5755_chan_reg_info(struct ad5755_state *st,
struct iio_chan_spec const *chan, long info, bool write,
unsigned int *reg, unsigned int *shift, unsigned int *offset)
......@@ -303,13 +294,15 @@ static int ad5755_read_raw(struct iio_dev *indio_dev,
{
struct ad5755_state *st = iio_priv(indio_dev);
unsigned int reg, shift, offset;
int min, max;
int ret;
switch (info) {
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = ad5755_get_scale(st, chan);
return IIO_VAL_INT_PLUS_NANO;
ad5755_get_min_max(st, chan, &min, &max);
*val = max - min;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
*val = ad5755_get_offset(st, chan);
return IIO_VAL_INT;
......
......@@ -217,7 +217,6 @@ static int ad5764_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info)
{
struct ad5764_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
unsigned int reg;
int vref;
int ret;
......@@ -245,15 +244,14 @@ static int ad5764_read_raw(struct iio_dev *indio_dev,
*val = sign_extend32(*val, 5);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/* vout = 4 * vref + ((dac_code / 65535) - 0.5) */
/* vout = 4 * vref + ((dac_code / 65536) - 0.5) */
vref = ad5764_get_channel_vref(st, chan->channel);
if (vref < 0)
return vref;
scale_uv = (vref * 4 * 100) >> chan->scan_type.realbits;
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
*val = vref * 4 / 1000;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
*val = -(1 << chan->scan_type.realbits) / 2;
return IIO_VAL_INT;
......
......@@ -270,9 +270,9 @@ static int ad5791_read_raw(struct iio_dev *indio_dev,
*val >>= chan->scan_type.shift;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->vref_mv;
*val2 = (1 << chan->scan_type.realbits) - 1;
return IIO_VAL_FRACTIONAL;
case IIO_CHAN_INFO_OFFSET:
val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits);
do_div(val64, st->vref_mv);
......
......@@ -82,15 +82,13 @@ static int max517_read_raw(struct iio_dev *indio_dev,
long m)
{
struct max517_data *data = iio_priv(indio_dev);
unsigned int scale_uv;
switch (m) {
case IIO_CHAN_INFO_SCALE:
/* Corresponds to Vref / 2^(bits) */
scale_uv = (data->vref_mv[chan->channel] * 1000) >> 8;
*val = scale_uv / 1000000;
*val2 = scale_uv % 1000000;
return IIO_VAL_INT_PLUS_MICRO;
*val = data->vref_mv[chan->channel];
*val2 = 8;
return IIO_VAL_FRACTIONAL_LOG2;
default:
break;
}
......
......@@ -239,17 +239,15 @@ static int mcp4725_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct mcp4725_data *data = iio_priv(indio_dev);
unsigned long scale_uv;
switch (mask) {
case IIO_CHAN_INFO_RAW:
*val = data->dac_value;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (data->vref_mv * 1000) >> 12;
*val = scale_uv / 1000000;
*val2 = scale_uv % 1000000;
return IIO_VAL_INT_PLUS_MICRO;
*val = data->vref_mv;
*val2 = 12;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
......
......@@ -51,7 +51,6 @@ static int adis16080_read_sample(struct iio_dev *indio_dev,
u16 addr, int *val)
{
struct adis16080_state *st = iio_priv(indio_dev);
struct spi_message m;
int ret;
struct spi_transfer t[] = {
{
......@@ -66,11 +65,7 @@ static int adis16080_read_sample(struct iio_dev *indio_dev,
st->buf = cpu_to_be16(addr | ADIS16080_DIN_WRITE);
spi_message_init(&m);
spi_message_add_tail(&t[0], &m);
spi_message_add_tail(&t[1], &m);
ret = spi_sync(st->us, &m);
ret = spi_sync_transfer(st->us, t, ARRAY_SIZE(t));
if (ret == 0)
*val = sign_extend32(be16_to_cpu(st->buf), 11);
......
......@@ -47,7 +47,6 @@ static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val)
{
int ret;
struct adis16130_state *st = iio_priv(indio_dev);
struct spi_message msg;
struct spi_transfer xfer = {
.tx_buf = st->buf,
.rx_buf = st->buf,
......@@ -59,10 +58,7 @@ static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val)
st->buf[0] = ADIS16130_CON_RD | reg_addr;
st->buf[1] = st->buf[2] = st->buf[3] = 0;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->us, &msg);
ret = spi_sync_transfer(st->us, &xfer, 1);
if (ret == 0)
*val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3];
mutex_unlock(&st->buf_lock);
......
......@@ -90,7 +90,6 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
u8 reg_address,
u16 *val)
{
struct spi_message msg;
struct adxrs450_state *st = iio_priv(indio_dev);
u32 tx;
int ret;
......@@ -114,10 +113,7 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
tx |= ADXRS450_P;
st->tx = cpu_to_be32(tx);
spi_message_init(&msg);
spi_message_add_tail(&xfers[0], &msg);
spi_message_add_tail(&xfers[1], &msg);
ret = spi_sync(st->us, &msg);
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
if (ret) {
dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n",
reg_address);
......@@ -169,7 +165,6 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev,
**/
static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val)
{
struct spi_message msg;
struct adxrs450_state *st = iio_priv(indio_dev);
int ret;
struct spi_transfer xfers[] = {
......@@ -188,10 +183,7 @@ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val)
mutex_lock(&st->buf_lock);
st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA);
spi_message_init(&msg);
spi_message_add_tail(&xfers[0], &msg);
spi_message_add_tail(&xfers[1], &msg);
ret = spi_sync(st->us, &msg);
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
if (ret) {
dev_err(&st->us->dev, "Problem while reading sensor data\n");
goto error_ret;
......
......@@ -275,6 +275,12 @@ static int hid_time_probe(struct platform_device *pdev)
return ret;
}
ret = sensor_hub_device_open(hsdev);
if (ret) {
dev_err(&pdev->dev, "failed to open sensor hub device!\n");
goto err_open;
}
time_state->rtc = devm_rtc_device_register(&pdev->dev,
"hid-sensor-time", &hid_time_rtc_ops,
THIS_MODULE);
......@@ -282,17 +288,24 @@ static int hid_time_probe(struct platform_device *pdev)
if (IS_ERR_OR_NULL(time_state->rtc)) {
ret = time_state->rtc ? PTR_ERR(time_state->rtc) : -ENODEV;
time_state->rtc = NULL;
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
dev_err(&pdev->dev, "rtc device register failed!\n");
goto err_rtc;
}
return ret;
err_rtc:
sensor_hub_device_close(hsdev);
err_open:
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
return ret;
}
static int hid_time_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
sensor_hub_device_close(hsdev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
return 0;
......
......@@ -13,6 +13,17 @@ Would be nice
3) Expand device set. Lots of other maxim adc's have very
similar interfaces.
MXS LRADC driver:
This is a classic MFD device as it combines the following subdevices
- touchscreen controller (input subsystem related device)
- general purpose ADC channels
- battery voltage monitor (power subsystem related device)
- die temperature monitor (thermal management)
At least the battery voltage and die temperature feature is required in-kernel
by a driver of the SoC's battery charging unit to avoid any damage to the
silicon and the battery.
TSL2561
Would be nice
1) Open question of userspace vs kernel space balance when
......
......@@ -102,7 +102,6 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
int addr)
{
struct adis16220_state *st = iio_priv(indio_dev);
struct spi_message msg;
struct spi_transfer xfers[] = {
{
.tx_buf = st->tx,
......@@ -147,10 +146,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
}
xfers[1].len = count;
spi_message_init(&msg);
spi_message_add_tail(&xfers[0], &msg);
spi_message_add_tail(&xfers[1], &msg);
ret = spi_sync(st->adis.spi, &msg);
ret = spi_sync_transfer(st->adis.spi, xfers, ARRAY_SIZE(xfers));
if (ret) {
mutex_unlock(&st->buf_lock);
......
......@@ -783,7 +783,6 @@ static int ad7280_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad7280_state *st = iio_priv(indio_dev);
unsigned int scale_uv;
int ret;
switch (m) {
......@@ -804,13 +803,12 @@ static int ad7280_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6)
scale_uv = (4000 * 1000) >> AD7280A_BITS;
*val = 4000;
else
scale_uv = (5000 * 1000) >> AD7280A_BITS;
*val = 5000;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val2 = AD7280A_BITS;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
......
......@@ -85,7 +85,6 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
{
int ret;
struct ad7606_state *st = iio_priv(indio_dev);
unsigned int scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
......@@ -101,11 +100,9 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
*val = (short) ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->range * 1000 * 2)
>> st->chip_info->channels[0].scan_type.realbits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->range * 2;
*val2 = st->chip_info->channels[0].scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
......
......@@ -90,17 +90,14 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad7780_state *st = iio_priv(indio_dev);
unsigned long scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
return ad_sigma_delta_single_conversion(indio_dev, chan, val);
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->int_vref_mv * 100000 * st->gain)
>> (chan->scan_type.realbits - 1);
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->int_vref_mv * st->gain;
*val2 = chan->scan_type.realbits - 1;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
*val -= (1 << (chan->scan_type.realbits - 1));
return IIO_VAL_INT;
......
......@@ -163,7 +163,6 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
{
int ret;
struct ad799x_state *st = iio_priv(indio_dev);
unsigned int scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
......@@ -180,10 +179,9 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
RES_MASK(chan->scan_type.realbits);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->int_vref_mv * 1000) >> chan->scan_type.realbits;
*val = scale_uv / 1000;
*val2 = (scale_uv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val = st->int_vref_mv;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
......
......@@ -35,6 +35,7 @@
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/clk.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
......@@ -129,11 +130,24 @@ enum mxs_lradc_ts {
MXS_LRADC_TOUCHSCREEN_5WIRE,
};
/*
* Touchscreen handling
*/
enum lradc_ts_plate {
LRADC_TOUCH = 0,
LRADC_SAMPLE_X,
LRADC_SAMPLE_Y,
LRADC_SAMPLE_PRESSURE,
LRADC_SAMPLE_VALID,
};
struct mxs_lradc {
struct device *dev;
void __iomem *base;
int irq[13];
struct clk *clk;
uint32_t *buffer;
struct iio_trigger *trig;
......@@ -169,32 +183,63 @@ struct mxs_lradc {
#define CHAN_MASK_TOUCHSCREEN_4WIRE (0xf << 2)
#define CHAN_MASK_TOUCHSCREEN_5WIRE (0x1f << 2)
enum mxs_lradc_ts use_touchscreen;
bool stop_touchscreen;
bool use_touchbutton;
struct input_dev *ts_input;
struct work_struct ts_work;
enum mxs_lradc_id soc;
enum lradc_ts_plate cur_plate; /* statemachine */
bool ts_valid;
unsigned ts_x_pos;
unsigned ts_y_pos;
unsigned ts_pressure;
/* handle touchscreen's physical behaviour */
/* samples per coordinate */
unsigned over_sample_cnt;
/* time clocks between samples */
unsigned over_sample_delay;
/* time in clocks to wait after the plates where switched */
unsigned settling_delay;
};
#define LRADC_CTRL0 0x00
#define LRADC_CTRL0_TOUCH_DETECT_ENABLE (1 << 23)
#define LRADC_CTRL0_TOUCH_SCREEN_TYPE (1 << 22)
#define LRADC_CTRL0_YNNSW /* YM */ (1 << 21)
#define LRADC_CTRL0_YPNSW /* YP */ (1 << 20)
#define LRADC_CTRL0_YPPSW /* YP */ (1 << 19)
#define LRADC_CTRL0_XNNSW /* XM */ (1 << 18)
#define LRADC_CTRL0_XNPSW /* XM */ (1 << 17)
#define LRADC_CTRL0_XPPSW /* XP */ (1 << 16)
#define LRADC_CTRL0_PLATE_MASK (0x3f << 16)
# define LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE (1 << 23)
# define LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE (1 << 22)
# define LRADC_CTRL0_MX28_YNNSW /* YM */ (1 << 21)
# define LRADC_CTRL0_MX28_YPNSW /* YP */ (1 << 20)
# define LRADC_CTRL0_MX28_YPPSW /* YP */ (1 << 19)
# define LRADC_CTRL0_MX28_XNNSW /* XM */ (1 << 18)
# define LRADC_CTRL0_MX28_XNPSW /* XM */ (1 << 17)
# define LRADC_CTRL0_MX28_XPPSW /* XP */ (1 << 16)
# define LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE (1 << 20)
# define LRADC_CTRL0_MX23_YM (1 << 19)
# define LRADC_CTRL0_MX23_XM (1 << 18)
# define LRADC_CTRL0_MX23_YP (1 << 17)
# define LRADC_CTRL0_MX23_XP (1 << 16)
# define LRADC_CTRL0_MX28_PLATE_MASK \
(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \
LRADC_CTRL0_MX28_YNNSW | LRADC_CTRL0_MX28_YPNSW | \
LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW | \
LRADC_CTRL0_MX28_XNPSW | LRADC_CTRL0_MX28_XPPSW)
# define LRADC_CTRL0_MX23_PLATE_MASK \
(LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE | \
LRADC_CTRL0_MX23_YM | LRADC_CTRL0_MX23_XM | \
LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XP)
#define LRADC_CTRL1 0x10
#define LRADC_CTRL1_TOUCH_DETECT_IRQ_EN (1 << 24)
#define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16))
#define LRADC_CTRL1_LRADC_IRQ_EN_MASK (0x1fff << 16)
#define LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK (0x1fff << 16)
#define LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK (0x01ff << 16)
#define LRADC_CTRL1_LRADC_IRQ_EN_OFFSET 16
#define LRADC_CTRL1_TOUCH_DETECT_IRQ (1 << 8)
#define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n))
#define LRADC_CTRL1_LRADC_IRQ_MASK 0x1fff
#define LRADC_CTRL1_MX28_LRADC_IRQ_MASK 0x1fff
#define LRADC_CTRL1_MX23_LRADC_IRQ_MASK 0x01ff
#define LRADC_CTRL1_LRADC_IRQ_OFFSET 0
#define LRADC_CTRL2 0x20
......@@ -207,19 +252,33 @@ struct mxs_lradc {
#define LRADC_CH_ACCUMULATE (1 << 29)
#define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24)
#define LRADC_CH_NUM_SAMPLES_OFFSET 24
#define LRADC_CH_NUM_SAMPLES(x) \
((x) << LRADC_CH_NUM_SAMPLES_OFFSET)
#define LRADC_CH_VALUE_MASK 0x3ffff
#define LRADC_CH_VALUE_OFFSET 0
#define LRADC_DELAY(n) (0xd0 + (0x10 * (n)))
#define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xff << 24)
#define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24
#define LRADC_DELAY_TRIGGER(x) \
(((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \
LRADC_DELAY_TRIGGER_LRADCS_MASK)
#define LRADC_DELAY_KICK (1 << 20)
#define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16)
#define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16
#define LRADC_DELAY_TRIGGER_DELAYS(x) \
(((x) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) & \
LRADC_DELAY_TRIGGER_DELAYS_MASK)
#define LRADC_DELAY_LOOP_COUNT_MASK (0x1f << 11)
#define LRADC_DELAY_LOOP_COUNT_OFFSET 11
#define LRADC_DELAY_LOOP(x) \
(((x) << LRADC_DELAY_LOOP_COUNT_OFFSET) & \
LRADC_DELAY_LOOP_COUNT_MASK)
#define LRADC_DELAY_DELAY_MASK 0x7ff
#define LRADC_DELAY_DELAY_OFFSET 0
#define LRADC_DELAY_DELAY(x) \
(((x) << LRADC_DELAY_DELAY_OFFSET) & \
LRADC_DELAY_DELAY_MASK)
#define LRADC_CTRL4 0x140
#define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4))
......@@ -228,295 +287,575 @@ struct mxs_lradc {
#define LRADC_RESOLUTION 12
#define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1)
/*
* Raw I/O operations
*/
static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan,
int *val, int *val2, long m)
static void mxs_lradc_reg_set(struct mxs_lradc *lradc, u32 val, u32 reg)
{
struct mxs_lradc *lradc = iio_priv(iio_dev);
int ret;
writel(val, lradc->base + reg + STMP_OFFSET_REG_SET);
}
if (m != IIO_CHAN_INFO_RAW)
return -EINVAL;
static void mxs_lradc_reg_clear(struct mxs_lradc *lradc, u32 val, u32 reg)
{
writel(val, lradc->base + reg + STMP_OFFSET_REG_CLR);
}
/* Check for invalid channel */
if (chan->channel > LRADC_MAX_TOTAL_CHANS)
return -EINVAL;
static void mxs_lradc_reg_wrt(struct mxs_lradc *lradc, u32 val, u32 reg)
{
writel(val, lradc->base + reg);
}
/*
* See if there is no buffered operation in progess. If there is, simply
* bail out. This can be improved to support both buffered and raw IO at
* the same time, yet the code becomes horribly complicated. Therefore I
* applied KISS principle here.
*/
ret = mutex_trylock(&lradc->lock);
if (!ret)
return -EBUSY;
static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc)
{
if (lradc->soc == IMX23_LRADC)
return LRADC_CTRL0_MX23_PLATE_MASK;
else
return LRADC_CTRL0_MX28_PLATE_MASK;
}
INIT_COMPLETION(lradc->completion);
static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc)
{
if (lradc->soc == IMX23_LRADC)
return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK;
else
return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK;
}
/*
* No buffered operation in progress, map the channel and trigger it.
* Virtual channel 0 is always used here as the others are always not
* used if doing raw sampling.
*/
writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc)
{
if (lradc->soc == IMX23_LRADC)
return LRADC_CTRL1_MX23_LRADC_IRQ_MASK;
else
return LRADC_CTRL1_MX28_LRADC_IRQ_MASK;
}
/* Clean the slot's previous content, then set new one. */
writel(LRADC_CTRL4_LRADCSELECT_MASK(0),
lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
writel(chan->channel, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
static u32 mxs_lradc_touch_detect_bit(struct mxs_lradc *lradc)
{
if (lradc->soc == IMX23_LRADC)
return LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE;
else
return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE;
}
writel(0, lradc->base + LRADC_CH(0));
static u32 mxs_lradc_drive_x_plate(struct mxs_lradc *lradc)
{
if (lradc->soc == IMX23_LRADC)
return LRADC_CTRL0_MX23_XP | LRADC_CTRL0_MX23_XM;
else
return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW;
}
/* Enable the IRQ and start sampling the channel. */
writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
writel(1 << 0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
static u32 mxs_lradc_drive_y_plate(struct mxs_lradc *lradc)
{
if (lradc->soc == IMX23_LRADC)
return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_YM;
else
return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW;
}
/* Wait for completion on the channel, 1 second max. */
ret = wait_for_completion_killable_timeout(&lradc->completion, HZ);
if (!ret)
ret = -ETIMEDOUT;
if (ret < 0)
goto err;
static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc)
{
if (lradc->soc == IMX23_LRADC)
return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XM;
else
return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW;
}
/* Read the data. */
*val = readl(lradc->base + LRADC_CH(0)) & LRADC_CH_VALUE_MASK;
ret = IIO_VAL_INT;
static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc)
{
return !!(readl(lradc->base + LRADC_STATUS) &
LRADC_STATUS_TOUCH_DETECT_RAW);
}
err:
writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
{
/*
* prepare for oversampling conversion
*
* from the datasheet:
* "The ACCUMULATE bit in the appropriate channel register
* HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
* otherwise, the IRQs will not fire."
*/
mxs_lradc_reg_wrt(lradc, LRADC_CH_ACCUMULATE |
LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1),
LRADC_CH(ch));
mutex_unlock(&lradc->lock);
/* from the datasheet:
* "Software must clear this register in preparation for a
* multi-cycle accumulation.
*/
mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch));
return ret;
}
/* prepare the delay/loop unit according to the oversampling count */
mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) |
LRADC_DELAY_TRIGGER_DELAYS(0) |
LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) |
LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
LRADC_DELAY(3));
static const struct iio_info mxs_lradc_iio_info = {
.driver_module = THIS_MODULE,
.read_raw = mxs_lradc_read_raw,
};
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
/*
* Touchscreen handling
/* wake us again, when the complete conversion is done */
mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1);
/*
* after changing the touchscreen plates setting
* the signals need some initial time to settle. Start the
* SoC's delay unit and start the conversion later
* and automatically.
*/
enum lradc_ts_plate {
LRADC_SAMPLE_X,
LRADC_SAMPLE_Y,
LRADC_SAMPLE_PRESSURE,
};
mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
LRADC_DELAY_KICK |
LRADC_DELAY_DELAY(lradc->settling_delay),
LRADC_DELAY(2));
}
static int mxs_lradc_ts_touched(struct mxs_lradc *lradc)
/*
* Pressure detection is special:
* We want to do both required measurements for the pressure detection in
* one turn. Use the hardware features to chain both conversions and let the
* hardware report one interrupt if both conversions are done
*/
static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1,
unsigned ch2)
{
uint32_t reg;
u32 reg;
/* Enable touch detection. */
writel(LRADC_CTRL0_PLATE_MASK,
lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
/*
* prepare for oversampling conversion
*
* from the datasheet:
* "The ACCUMULATE bit in the appropriate channel register
* HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
* otherwise, the IRQs will not fire."
*/
reg = LRADC_CH_ACCUMULATE |
LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1);
mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch1));
mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch2));
/* from the datasheet:
* "Software must clear this register in preparation for a
* multi-cycle accumulation.
*/
mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch1));
mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch2));
/* prepare the delay/loop unit according to the oversampling count */
mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch1) |
LRADC_DELAY_TRIGGER(1 << ch2) | /* start both channels */
LRADC_DELAY_TRIGGER_DELAYS(0) |
LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) |
LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
LRADC_DELAY(3));
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
/* wake us again, when the conversions are done */
mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1);
/*
* after changing the touchscreen plates setting
* the signals need some initial time to settle. Start the
* SoC's delay unit and start the conversion later
* and automatically.
*/
mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
LRADC_DELAY_KICK |
LRADC_DELAY_DELAY(lradc->settling_delay), LRADC_DELAY(2));
}
msleep(LRADC_TS_SAMPLE_DELAY_MS);
static unsigned mxs_lradc_read_raw_channel(struct mxs_lradc *lradc,
unsigned channel)
{
u32 reg;
unsigned num_samples, val;
reg = readl(lradc->base + LRADC_STATUS);
reg = readl(lradc->base + LRADC_CH(channel));
if (reg & LRADC_CH_ACCUMULATE)
num_samples = lradc->over_sample_cnt;
else
num_samples = 1;
return reg & LRADC_STATUS_TOUCH_DETECT_RAW;
val = (reg & LRADC_CH_VALUE_MASK) >> LRADC_CH_VALUE_OFFSET;
return val / num_samples;
}
static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc,
enum lradc_ts_plate plate, int change)
static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc,
unsigned ch1, unsigned ch2)
{
unsigned long delay, jiff;
uint32_t reg, ctrl0 = 0, chan = 0;
/* The touchscreen always uses CTRL4 slot #7. */
const uint8_t slot = 7;
uint32_t val;
u32 reg, mask;
unsigned pressure, m1, m2;
/*
* There are three correct configurations of the controller sampling
* the touchscreen, each of these configuration provides different
* information from the touchscreen.
*
* The following table describes the sampling configurations:
* +-------------+-------+-------+-------+
* | Wire \ Axis | X | Y | Z |
* +---------------------+-------+-------+
* | X+ (CH2) | HI | TS | TS |
* +-------------+-------+-------+-------+
* | X- (CH4) | LO | SH | HI |
* +-------------+-------+-------+-------+
* | Y+ (CH3) | SH | HI | HI |
* +-------------+-------+-------+-------+
* | Y- (CH5) | TS | LO | SH |
* +-------------+-------+-------+-------+
*
* HI ... strong '1' ; LO ... strong '0'
* SH ... sample here ; TS ... tri-state
*
* There are a few other ways of obtaining the Z coordinate
* (aka. pressure), but the one in the table seems to be the
* most reliable one.
*/
switch (plate) {
case LRADC_SAMPLE_X:
ctrl0 = LRADC_CTRL0_XPPSW | LRADC_CTRL0_XNNSW;
chan = 3;
break;
case LRADC_SAMPLE_Y:
ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_YNNSW;
chan = 4;
break;
case LRADC_SAMPLE_PRESSURE:
ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_XNNSW;
chan = 5;
break;
mask = LRADC_CTRL1_LRADC_IRQ(ch1) | LRADC_CTRL1_LRADC_IRQ(ch2);
reg = readl(lradc->base + LRADC_CTRL1) & mask;
while (reg != mask) {
reg = readl(lradc->base + LRADC_CTRL1) & mask;
dev_dbg(lradc->dev, "One channel is still busy: %X\n", reg);
}
if (change) {
writel(LRADC_CTRL0_PLATE_MASK,
lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
writel(ctrl0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
m1 = mxs_lradc_read_raw_channel(lradc, ch1);
m2 = mxs_lradc_read_raw_channel(lradc, ch2);
writel(LRADC_CTRL4_LRADCSELECT_MASK(slot),
lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
writel(chan << LRADC_CTRL4_LRADCSELECT_OFFSET(slot),
lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
if (m2 == 0) {
dev_warn(lradc->dev, "Cannot calculate pressure\n");
return 1 << (LRADC_RESOLUTION - 1);
}
writel(0xffffffff, lradc->base + LRADC_CH(slot) + STMP_OFFSET_REG_CLR);
writel(1 << slot, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
/* simply scale the value from 0 ... max ADC resolution */
pressure = m1;
pressure *= (1 << LRADC_RESOLUTION);
pressure /= m2;
delay = jiffies + msecs_to_jiffies(LRADC_TS_SAMPLE_DELAY_MS);
do {
jiff = jiffies;
reg = readl_relaxed(lradc->base + LRADC_CTRL1);
if (reg & LRADC_CTRL1_LRADC_IRQ(slot))
break;
} while (time_before(jiff, delay));
dev_dbg(lradc->dev, "Pressure = %u\n", pressure);
return pressure;
}
writel(LRADC_CTRL1_LRADC_IRQ(slot),
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
#define TS_CH_XP 2
#define TS_CH_YP 3
#define TS_CH_XM 4
#define TS_CH_YM 5
if (time_after_eq(jiff, delay))
return -ETIMEDOUT;
static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc)
{
u32 reg;
int val;
reg = readl(lradc->base + LRADC_CTRL1);
/* only channels 3 to 5 are of interest here */
if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) {
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) |
LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1);
val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP);
} else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) {
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) |
LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1);
val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM);
} else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) {
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) |
LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1);
val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM);
} else {
return -EIO;
}
val = readl(lradc->base + LRADC_CH(slot));
val &= LRADC_CH_VALUE_MASK;
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
return val;
}
static int32_t mxs_lradc_ts_sample_filter(struct mxs_lradc *lradc,
enum lradc_ts_plate plate)
/*
* YP(open)--+-------------+
* | |--+
* | | |
* YM(-)--+-------------+ |
* +--------------+
* | |
* XP(weak+) XM(open)
*
* "weak+" means 200k Ohm VDDIO
* (-) means GND
*/
static void mxs_lradc_setup_touch_detection(struct mxs_lradc *lradc)
{
int32_t val, tot = 0;
int i;
/*
* In order to detect a touch event the 'touch detect enable' bit
* enables:
* - a weak pullup to the X+ connector
* - a strong ground at the Y- connector
*/
mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc),
LRADC_CTRL0);
}
val = mxs_lradc_ts_sample(lradc, plate, 1);
/*
* YP(meas)--+-------------+
* | |--+
* | | |
* YM(open)--+-------------+ |
* +--------------+
* | |
* XP(+) XM(-)
*
* (+) means here 1.85 V
* (-) means here GND
*/
static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc)
{
mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0);
/* Delay a bit so the touchscreen is stable. */
mdelay(2);
lradc->cur_plate = LRADC_SAMPLE_X;
mxs_lradc_setup_ts_channel(lradc, TS_CH_YP);
}
for (i = 0; i < LRADC_TS_SAMPLE_AMOUNT; i++) {
val = mxs_lradc_ts_sample(lradc, plate, 0);
tot += val;
}
/*
* YP(+)--+-------------+
* | |--+
* | | |
* YM(-)--+-------------+ |
* +--------------+
* | |
* XP(open) XM(meas)
*
* (+) means here 1.85 V
* (-) means here GND
*/
static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc)
{
mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0);
lradc->cur_plate = LRADC_SAMPLE_Y;
mxs_lradc_setup_ts_channel(lradc, TS_CH_XM);
}
/*
* YP(+)--+-------------+
* | |--+
* | | |
* YM(meas)--+-------------+ |
* +--------------+
* | |
* XP(meas) XM(-)
*
* (+) means here 1.85 V
* (-) means here GND
*/
static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc)
{
mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0);
lradc->cur_plate = LRADC_SAMPLE_PRESSURE;
mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
}
static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
{
mxs_lradc_setup_touch_detection(lradc);
return tot / LRADC_TS_SAMPLE_AMOUNT;
lradc->cur_plate = LRADC_TOUCH;
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ |
LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
}
static void mxs_lradc_ts_work(struct work_struct *ts_work)
static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc)
{
struct mxs_lradc *lradc = container_of(ts_work,
struct mxs_lradc, ts_work);
int val_x, val_y, val_p;
bool valid = false;
while (mxs_lradc_ts_touched(lradc)) {
/* Disable touch detector so we can sample the touchscreen. */
writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
if (likely(valid)) {
input_report_abs(lradc->ts_input, ABS_X, val_x);
input_report_abs(lradc->ts_input, ABS_Y, val_y);
input_report_abs(lradc->ts_input, ABS_PRESSURE, val_p);
input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos);
input_report_abs(lradc->ts_input, ABS_Y, lradc->ts_y_pos);
input_report_abs(lradc->ts_input, ABS_PRESSURE, lradc->ts_pressure);
input_report_key(lradc->ts_input, BTN_TOUCH, 1);
input_sync(lradc->ts_input);
}
}
valid = false;
static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc)
{
mxs_lradc_setup_touch_detection(lradc);
lradc->cur_plate = LRADC_SAMPLE_VALID;
/*
* start a dummy conversion to burn time to settle the signals
* note: we are not interested in the conversion's value
*/
mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5));
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1);
mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) |
LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */
LRADC_DELAY(2));
}
val_x = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_X);
if (val_x < 0)
continue;
val_y = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_Y);
if (val_y < 0)
continue;
val_p = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_PRESSURE);
if (val_p < 0)
continue;
/*
* in order to avoid false measurements, report only samples where
* the surface is still touched after the position measurement
*/
static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid)
{
/* if it is still touched, report the sample */
if (valid && mxs_lradc_check_touch_event(lradc)) {
lradc->ts_valid = true;
mxs_lradc_report_ts_event(lradc);
}
valid = true;
/* if it is even still touched, continue with the next measurement */
if (mxs_lradc_check_touch_event(lradc)) {
mxs_lradc_prepare_y_pos(lradc);
return;
}
input_report_abs(lradc->ts_input, ABS_PRESSURE, 0);
if (lradc->ts_valid) {
/* signal the release */
lradc->ts_valid = false;
input_report_key(lradc->ts_input, BTN_TOUCH, 0);
input_sync(lradc->ts_input);
}
/* if it is released, wait for the next touch via IRQ */
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
}
/* Do not restart the TS IRQ if the driver is shutting down. */
if (lradc->stop_touchscreen)
/* touchscreen's state machine */
static void mxs_lradc_handle_touch(struct mxs_lradc *lradc)
{
int val;
switch (lradc->cur_plate) {
case LRADC_TOUCH:
/*
* start with the Y-pos, because it uses nearly the same plate
* settings like the touch detection
*/
if (mxs_lradc_check_touch_event(lradc)) {
mxs_lradc_reg_clear(lradc,
LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
LRADC_CTRL1);
mxs_lradc_prepare_y_pos(lradc);
}
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ,
LRADC_CTRL1);
return;
case LRADC_SAMPLE_Y:
val = mxs_lradc_read_ts_channel(lradc);
if (val < 0) {
mxs_lradc_enable_touch_detection(lradc); /* re-start */
return;
}
lradc->ts_y_pos = val;
mxs_lradc_prepare_x_pos(lradc);
return;
/* Restart the touchscreen interrupts. */
writel(LRADC_CTRL1_TOUCH_DETECT_IRQ,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
case LRADC_SAMPLE_X:
val = mxs_lradc_read_ts_channel(lradc);
if (val < 0) {
mxs_lradc_enable_touch_detection(lradc); /* re-start */
return;
}
lradc->ts_x_pos = val;
mxs_lradc_prepare_pressure(lradc);
return;
case LRADC_SAMPLE_PRESSURE:
lradc->ts_pressure =
mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
mxs_lradc_complete_touch_event(lradc);
return;
case LRADC_SAMPLE_VALID:
val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */
mxs_lradc_finish_touch_event(lradc, 1);
break;
}
}
static int mxs_lradc_ts_open(struct input_dev *dev)
/*
* Raw I/O operations
*/
static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan,
int *val, int *val2, long m)
{
struct mxs_lradc *lradc = input_get_drvdata(dev);
struct mxs_lradc *lradc = iio_priv(iio_dev);
int ret;
/* The touchscreen is starting. */
lradc->stop_touchscreen = false;
if (m != IIO_CHAN_INFO_RAW)
return -EINVAL;
/* Enable the touch-detect circuitry. */
writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
/* Check for invalid channel */
if (chan->channel > LRADC_MAX_TOTAL_CHANS)
return -EINVAL;
/* Enable the touch-detect IRQ. */
writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
/*
* See if there is no buffered operation in progess. If there is, simply
* bail out. This can be improved to support both buffered and raw IO at
* the same time, yet the code becomes horribly complicated. Therefore I
* applied KISS principle here.
*/
ret = mutex_trylock(&lradc->lock);
if (!ret)
return -EBUSY;
return 0;
INIT_COMPLETION(lradc->completion);
/*
* No buffered operation in progress, map the channel and trigger it.
* Virtual channel 0 is always used here as the others are always not
* used if doing raw sampling.
*/
if (lradc->soc == IMX28_LRADC)
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
LRADC_CTRL1);
mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
/* Clean the slot's previous content, then set new one. */
mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(0), LRADC_CTRL4);
mxs_lradc_reg_set(lradc, chan->channel, LRADC_CTRL4);
mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(0));
/* Enable the IRQ and start sampling the channel. */
mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1);
mxs_lradc_reg_set(lradc, 1 << 0, LRADC_CTRL0);
/* Wait for completion on the channel, 1 second max. */
ret = wait_for_completion_killable_timeout(&lradc->completion, HZ);
if (!ret)
ret = -ETIMEDOUT;
if (ret < 0)
goto err;
/* Read the data. */
*val = readl(lradc->base + LRADC_CH(0)) & LRADC_CH_VALUE_MASK;
ret = IIO_VAL_INT;
err:
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1);
mutex_unlock(&lradc->lock);
return ret;
}
static void mxs_lradc_ts_close(struct input_dev *dev)
static const struct iio_info mxs_lradc_iio_info = {
.driver_module = THIS_MODULE,
.read_raw = mxs_lradc_read_raw,
};
static int mxs_lradc_ts_open(struct input_dev *dev)
{
struct mxs_lradc *lradc = input_get_drvdata(dev);
/* Indicate the touchscreen is stopping. */
lradc->stop_touchscreen = true;
mb();
/* Enable the touch-detect circuitry. */
mxs_lradc_enable_touch_detection(lradc);
/* Wait until touchscreen thread finishes any possible remnants. */
cancel_work_sync(&lradc->ts_work);
return 0;
}
/* Disable touchscreen touch-detect IRQ. */
writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
static void mxs_lradc_disable_ts(struct mxs_lradc *lradc)
{
/* stop all interrupts from firing */
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) |
LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5),
LRADC_CTRL1);
/* Power-down touchscreen touch-detect circuitry. */
writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
}
static void mxs_lradc_ts_close(struct input_dev *dev)
{
struct mxs_lradc *lradc = input_get_drvdata(dev);
mxs_lradc_disable_ts(lradc);
}
static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
......@@ -562,8 +901,7 @@ static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc)
if (!lradc->use_touchscreen)
return;
cancel_work_sync(&lradc->ts_work);
mxs_lradc_disable_ts(lradc);
input_unregister_device(lradc->ts_input);
}
......@@ -576,31 +914,24 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
struct mxs_lradc *lradc = iio_priv(iio);
unsigned long reg = readl(lradc->base + LRADC_CTRL1);
const uint32_t ts_irq_mask =
LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
LRADC_CTRL1_TOUCH_DETECT_IRQ;
LRADC_CTRL1_TOUCH_DETECT_IRQ |
LRADC_CTRL1_LRADC_IRQ(2) |
LRADC_CTRL1_LRADC_IRQ(3) |
LRADC_CTRL1_LRADC_IRQ(4) |
LRADC_CTRL1_LRADC_IRQ(5);
if (!(reg & LRADC_CTRL1_LRADC_IRQ_MASK))
if (!(reg & mxs_lradc_irq_mask(lradc)))
return IRQ_NONE;
/*
* Touchscreen IRQ handling code has priority and therefore
* is placed here. In case touchscreen IRQ arrives, disable
* it ASAP
*/
if (reg & LRADC_CTRL1_TOUCH_DETECT_IRQ) {
writel(ts_irq_mask,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
if (!lradc->stop_touchscreen)
schedule_work(&lradc->ts_work);
}
if (lradc->use_touchscreen && (reg & ts_irq_mask))
mxs_lradc_handle_touch(lradc);
if (iio_buffer_enabled(iio))
iio_trigger_poll(iio->trig, iio_get_time_ns());
else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
complete(&lradc->completion);
writel(reg & LRADC_CTRL1_LRADC_IRQ_MASK,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1);
return IRQ_HANDLED;
}
......@@ -619,7 +950,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
for_each_set_bit(i, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
lradc->buffer[j] = readl(lradc->base + LRADC_CH(j));
writel(chan_value, lradc->base + LRADC_CH(j));
mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(j));
lradc->buffer[j] &= LRADC_CH_VALUE_MASK;
lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP;
j++;
......@@ -638,7 +969,7 @@ static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state)
struct mxs_lradc *lradc = iio_priv(iio);
const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR;
writel(LRADC_DELAY_KICK, lradc->base + LRADC_DELAY(0) + st);
mxs_lradc_reg_wrt(lradc, LRADC_DELAY_KICK, LRADC_DELAY(0) + st);
return 0;
}
......@@ -714,29 +1045,27 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
if (ret < 0)
goto err_buf;
writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
if (lradc->soc == IMX28_LRADC)
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
LRADC_CTRL1);
mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs);
ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs);
writel(chan_value, lradc->base + LRADC_CH(ofs));
mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(ofs));
bitmap_set(&enable, ofs, 1);
ofs++;
}
writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
writel(ctrl4_clr, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
writel(ctrl4_set, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
writel(ctrl1_irq, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
writel(enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET,
lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_SET);
mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK |
LRADC_DELAY_KICK, LRADC_DELAY(0));
mxs_lradc_reg_clear(lradc, ctrl4_clr, LRADC_CTRL4);
mxs_lradc_reg_set(lradc, ctrl4_set, LRADC_CTRL4);
mxs_lradc_reg_set(lradc, ctrl1_irq, LRADC_CTRL1);
mxs_lradc_reg_set(lradc, enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET,
LRADC_DELAY(0));
return 0;
......@@ -751,12 +1080,13 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio)
{
struct mxs_lradc *lradc = iio_priv(iio);
writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK |
LRADC_DELAY_KICK, LRADC_DELAY(0));
writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
if (lradc->soc == IMX28_LRADC)
mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
LRADC_CTRL1);
kfree(lradc->buffer);
mutex_unlock(&lradc->lock);
......@@ -851,24 +1181,25 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
return ret;
/* Configure DELAY CHANNEL 0 for generic ADC sampling. */
writel(adc_cfg, lradc->base + LRADC_DELAY(0));
mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0));
/* Disable remaining DELAY CHANNELs */
writel(0, lradc->base + LRADC_DELAY(1));
writel(0, lradc->base + LRADC_DELAY(2));
writel(0, lradc->base + LRADC_DELAY(3));
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(1));
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
/* Configure the touchscreen type */
writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE,
lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
if (lradc->soc == IMX28_LRADC) {
mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
LRADC_CTRL0);
if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) {
writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE,
lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE)
mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
LRADC_CTRL0);
}
/* Start internal temperature sensing. */
writel(0, lradc->base + LRADC_CTRL2);
mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2);
return 0;
}
......@@ -877,11 +1208,10 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
{
int i;
writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1);
for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
writel(0, lradc->base + LRADC_DELAY(i));
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i));
}
static const struct of_device_id mxs_lradc_dt_ids[] = {
......@@ -891,6 +1221,52 @@ static const struct of_device_id mxs_lradc_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids);
static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc,
struct device_node *lradc_node)
{
int ret;
u32 ts_wires = 0, adapt;
ret = of_property_read_u32(lradc_node, "fsl,lradc-touchscreen-wires",
&ts_wires);
if (ret)
return -ENODEV; /* touchscreen feature disabled */
switch (ts_wires) {
case 4:
lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE;
break;
case 5:
if (lradc->soc == IMX28_LRADC) {
lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE;
break;
}
/* fall through an error message for i.MX23 */
default:
dev_err(lradc->dev,
"Unsupported number of touchscreen wires (%d)\n",
ts_wires);
return -EINVAL;
}
lradc->over_sample_cnt = 4;
ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt);
if (ret == 0)
lradc->over_sample_cnt = adapt;
lradc->over_sample_delay = 2;
ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt);
if (ret == 0)
lradc->over_sample_delay = adapt;
lradc->settling_delay = 10;
ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt);
if (ret == 0)
lradc->settling_delay = adapt;
return 0;
}
static int mxs_lradc_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
......@@ -902,8 +1278,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
struct mxs_lradc *lradc;
struct iio_dev *iio;
struct resource *iores;
uint32_t ts_wires = 0;
int ret = 0;
int ret = 0, touch_ret;
int i;
/* Allocate the IIO device. */
......@@ -914,6 +1289,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
}
lradc = iio_priv(iio);
lradc->soc = (enum mxs_lradc_id)of_id->data;
/* Grab the memory area */
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......@@ -922,20 +1298,18 @@ static int mxs_lradc_probe(struct platform_device *pdev)
if (IS_ERR(lradc->base))
return PTR_ERR(lradc->base);
INIT_WORK(&lradc->ts_work, mxs_lradc_ts_work);
lradc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(lradc->clk)) {
dev_err(dev, "Failed to get the delay unit clock\n");
return PTR_ERR(lradc->clk);
}
ret = clk_prepare_enable(lradc->clk);
if (ret != 0) {
dev_err(dev, "Failed to enable the delay unit clock\n");
return ret;
}
/* Check if touchscreen is enabled in DT. */
ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
&ts_wires);
if (ret)
dev_info(dev, "Touchscreen not enabled.\n");
else if (ts_wires == 4)
lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE;
else if (ts_wires == 5)
lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE;
else
dev_warn(dev, "Unsupported number of touchscreen wires (%d)\n",
ts_wires);
touch_ret = mxs_lradc_probe_touchscreen(lradc, node);
/* Grab all IRQ sources */
for (i = 0; i < of_cfg->irq_count; i++) {
......@@ -979,9 +1353,11 @@ static int mxs_lradc_probe(struct platform_device *pdev)
goto err_dev;
/* Register the touchscreen input device. */
if (touch_ret == 0) {
ret = mxs_lradc_ts_register(lradc);
if (ret)
goto err_ts_register;
}
/* Register IIO device. */
ret = iio_device_register(iio);
......@@ -1014,6 +1390,7 @@ static int mxs_lradc_remove(struct platform_device *pdev)
mxs_lradc_trigger_remove(iio);
iio_triggered_buffer_cleanup(iio);
clk_disable_unprepare(lradc->clk);
return 0;
}
......
......@@ -168,10 +168,9 @@ static int spear_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
scale_mv = (info->vref_external * 1000) >> DATA_BITS;
*val = scale_mv / 1000;
*val2 = (scale_mv % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO;
*val = info->vref_external;
*val2 = DATA_BITS;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
......
......@@ -656,20 +656,21 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
switch (chan->type) {
case IIO_CAPACITANCE:
/* 8.192pf / 2^24 */
*val2 = 488;
*val = 0;
*val2 = 488;
ret = IIO_VAL_INT_PLUS_NANO;
break;
case IIO_VOLTAGE:
/* 1170mV / 2^23 */
*val2 = 139475;
*val = 0;
*val = 1170;
*val2 = 23;
ret = IIO_VAL_FRACTIONAL_LOG2;
break;
default:
ret = -EINVAL;
goto out;
break;
}
ret = IIO_VAL_INT_PLUS_NANO;
break;
default:
ret = -EINVAL;
......
......@@ -67,7 +67,6 @@ static ssize_t ad9852_set_parameter(struct device *dev,
const char *buf,
size_t len)
{
struct spi_message msg;
struct spi_transfer xfer;
int ret;
struct ad9852_config *config = (struct ad9852_config *)buf;
......@@ -78,99 +77,77 @@ static ssize_t ad9852_set_parameter(struct device *dev,
xfer.tx_buf = &config->phajst0[0];
mutex_lock(&st->lock);
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->phajst1[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 6;
xfer.tx_buf = &config->fretun1[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 6;
xfer.tx_buf = &config->fretun2[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 6;
xfer.tx_buf = &config->dltafre[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->updtclk[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 4;
xfer.tx_buf = &config->ramprat[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->control[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->outpskm[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 2;
xfer.tx_buf = &config->outpskr[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->daccntl[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
......
......@@ -119,7 +119,6 @@ static ssize_t ad9910_set_parameter(struct device *dev,
const char *buf,
size_t len)
{
struct spi_message msg;
struct spi_transfer xfer;
int ret;
struct ad9910_config *config = (struct ad9910_config *)buf;
......@@ -130,152 +129,118 @@ static ssize_t ad9910_set_parameter(struct device *dev,
xfer.tx_buf = &config->auxdac[0];
mutex_lock(&st->lock);
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->ioupd[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->ftw[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->pow[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->asf[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->multc[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->dig_rampl[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->dig_ramps[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->dig_rampr[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep0[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep1[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep2[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep3[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep4[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep5[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep6[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 9;
xfer.tx_buf = &config->sin_tonep7[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
......@@ -288,7 +253,6 @@ static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0);
static void ad9910_init(struct ad9910_state *st)
{
struct spi_message msg;
struct spi_transfer xfer;
int ret;
u8 cfr[5];
......@@ -304,9 +268,7 @@ static void ad9910_init(struct ad9910_state *st)
xfer.len = 5;
xfer.tx_buf = &cfr;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
......@@ -319,9 +281,7 @@ static void ad9910_init(struct ad9910_state *st)
xfer.len = 5;
xfer.tx_buf = &cfr;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
......@@ -334,9 +294,7 @@ static void ad9910_init(struct ad9910_state *st)
xfer.len = 5;
xfer.tx_buf = &cfr;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
......
......@@ -60,7 +60,6 @@ static ssize_t ad9951_set_parameter(struct device *dev,
const char *buf,
size_t len)
{
struct spi_message msg;
struct spi_transfer xfer;
int ret;
struct ad9951_config *config = (struct ad9951_config *)buf;
......@@ -71,36 +70,28 @@ static ssize_t ad9951_set_parameter(struct device *dev,
xfer.tx_buf = &config->asf[0];
mutex_lock(&st->lock);
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 2;
xfer.tx_buf = &config->arr[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 5;
xfer.tx_buf = &config->ftw0[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
xfer.len = 3;
xfer.tx_buf = &config->ftw1[0];
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
error_ret:
......@@ -113,7 +104,6 @@ static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9951_set_parameter, 0);
static void ad9951_init(struct ad9951_state *st)
{
struct spi_message msg;
struct spi_transfer xfer;
int ret;
u8 cfr[5];
......@@ -129,9 +119,7 @@ static void ad9951_init(struct ad9951_state *st)
xfer.len = 5;
xfer.tx_buf = &cfr;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
......@@ -143,9 +131,7 @@ static void ad9951_init(struct ad9951_state *st)
xfer.len = 4;
xfer.tx_buf = &cfr;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->sdev, &msg);
ret = spi_sync_transfer(st->sdev, &xfer, 1);
if (ret)
goto error_ret;
......
......@@ -29,16 +29,11 @@
#define HMC5843_CONFIG_REG_B 0x01
#define HMC5843_MODE_REG 0x02
#define HMC5843_DATA_OUT_X_MSB_REG 0x03
#define HMC5843_DATA_OUT_X_LSB_REG 0x04
#define HMC5843_DATA_OUT_Y_MSB_REG 0x05
#define HMC5843_DATA_OUT_Y_LSB_REG 0x06
#define HMC5843_DATA_OUT_Z_MSB_REG 0x07
#define HMC5843_DATA_OUT_Z_LSB_REG 0x08
/* Beware: Y and Z are exchanged on HMC5883 */
#define HMC5883_DATA_OUT_Z_MSB_REG 0x05
#define HMC5883_DATA_OUT_Z_LSB_REG 0x06
#define HMC5883_DATA_OUT_Y_MSB_REG 0x07
#define HMC5883_DATA_OUT_Y_LSB_REG 0x08
#define HMC5843_STATUS_REG 0x09
enum hmc5843_ids {
......@@ -56,17 +51,11 @@ enum hmc5843_ids {
#define HMC5843_RANGE_GAIN_DEFAULT 0x01
#define HMC5843_RANGE_GAIN_MAX 0x07
/*
* Device status
*/
/* Device status */
#define HMC5843_DATA_READY 0x01
#define HMC5843_DATA_OUTPUT_LOCK 0x02
/* Does not exist on HMC5883, not used */
#define HMC5843_VOLTAGE_REGULATOR_ENABLED 0x04
/*
* Mode register configuration
*/
/* Mode register configuration */
#define HMC5843_MODE_CONVERSION_CONTINUOUS 0x00
#define HMC5843_MODE_CONVERSION_SINGLE 0x01
#define HMC5843_MODE_IDLE 0x02
......@@ -78,21 +67,18 @@ enum hmc5843_ids {
* HMC5883: Typical data output rate
*/
#define HMC5843_RATE_OFFSET 0x02
#define HMC5843_RATE_DEFAULT 0x04
#define HMC5843_RATE_BITMASK 0x1C
#define HMC5843_RATE_NOT_USED 0x07
/*
* Device measurement configuration
*/
/* Device measurement configuration */
#define HMC5843_MEAS_CONF_NORMAL 0x00
#define HMC5843_MEAS_CONF_POSITIVE_BIAS 0x01
#define HMC5843_MEAS_CONF_NEGATIVE_BIAS 0x02
#define HMC5843_MEAS_CONF_NOT_USED 0x03
#define HMC5843_MEAS_CONF_MASK 0x03
/*
* Scaling factors: 10000000/Gain
*/
/* Scaling factors: 10000000/Gain */
static const int hmc5843_regval_to_nanoscale[] = {
6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
};
......@@ -164,24 +150,26 @@ static const int hmc5883l_regval_to_input_field_mga[] = {
* 6 | 50 | 75
* 7 | Not used | Not used
*/
static const char * const hmc5843_regval_to_sample_freq[] = {
"0.5", "1", "2", "5", "10", "20", "50",
static const int hmc5843_regval_to_samp_freq[7][2] = {
{0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0}
};
static const char * const hmc5883_regval_to_sample_freq[] = {
"0.75", "1.5", "3", "7.5", "15", "30", "75",
static const int hmc5883_regval_to_samp_freq[7][2] = {
{0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0},
{75, 0}
};
/* Describe chip variants */
struct hmc5843_chip_info {
const struct iio_chan_spec *channels;
const char * const *regval_to_sample_freq;
const int (*regval_to_samp_freq)[2];
const int *regval_to_input_field_mga;
const int *regval_to_nanoscale;
};
/* Each client has this additional data */
struct hmc5843_data {
struct i2c_client *client;
struct mutex lock;
u8 rate;
u8 meas_conf;
......@@ -200,18 +188,15 @@ static s32 hmc5843_configure(struct i2c_client *client,
}
/* Return the measurement value from the specified channel */
static int hmc5843_read_measurement(struct iio_dev *indio_dev,
int address,
int *val)
static int hmc5843_read_measurement(struct hmc5843_data *data,
int address, int *val)
{
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct hmc5843_data *data = iio_priv(indio_dev);
s32 result;
int tries = 150;
mutex_lock(&data->lock);
while (tries-- > 0) {
result = i2c_smbus_read_byte_data(client,
result = i2c_smbus_read_byte_data(data->client,
HMC5843_STATUS_REG);
if (result & HMC5843_DATA_READY)
break;
......@@ -219,12 +204,12 @@ static int hmc5843_read_measurement(struct iio_dev *indio_dev,
}
if (tries < 0) {
dev_err(&client->dev, "data not ready\n");
dev_err(&data->client->dev, "data not ready\n");
mutex_unlock(&data->lock);
return -EIO;
}
result = i2c_smbus_read_word_swapped(client, address);
result = i2c_smbus_read_word_swapped(data->client, address);
mutex_unlock(&data->lock);
if (result < 0)
return -EINVAL;
......@@ -318,15 +303,13 @@ static IIO_DEVICE_ATTR(operating_mode,
* and BN.
*
*/
static s32 hmc5843_set_meas_conf(struct i2c_client *client,
u8 meas_conf)
static s32 hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct hmc5843_data *data = iio_priv(indio_dev);
u8 reg_val;
reg_val = (meas_conf & HMC5843_MEAS_CONF_MASK) |
(data->rate << HMC5843_RATE_OFFSET);
return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val);
return i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A,
reg_val);
}
static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
......@@ -344,7 +327,6 @@ static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
size_t count)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct hmc5843_data *data = iio_priv(indio_dev);
unsigned long meas_conf = 0;
int error;
......@@ -357,7 +339,7 @@ static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
mutex_lock(&data->lock);
dev_dbg(dev, "set measurement configuration to %lu\n", meas_conf);
if (hmc5843_set_meas_conf(client, meas_conf)) {
if (hmc5843_set_meas_conf(data, meas_conf)) {
count = -EINVAL;
goto exit;
}
......@@ -374,111 +356,62 @@ static IIO_DEVICE_ATTR(meas_conf,
hmc5843_set_measurement_configuration,
0);
static ssize_t hmc5843_show_sampling_frequencies_available(struct device *dev,
struct device_attribute *attr,
char *buf)
static ssize_t hmc5843_show_int_plus_micros(char *buf,
const int (*vals)[2], int n)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct hmc5843_data *data = iio_priv(indio_dev);
ssize_t total_n = 0;
size_t len = 0;
int i;
for (i = 0; i < HMC5843_RATE_NOT_USED; i++) {
ssize_t n = sprintf(buf, "%s ", data->variant->regval_to_sample_freq[i]);
buf += n;
total_n += n;
}
/* replace trailing space by newline */
buf[-1] = '\n';
return total_n;
}
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_sampling_frequencies_available);
for (i = 0; i < n; i++)
len += scnprintf(buf + len, PAGE_SIZE - len,
"%d.%d ", vals[i][0], vals[i][1]);
static s32 hmc5843_set_rate(struct i2c_client *client,
u8 rate)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct hmc5843_data *data = iio_priv(indio_dev);
u8 reg_val;
if (rate >= HMC5843_RATE_NOT_USED) {
dev_err(&client->dev,
"data output rate is not supported\n");
return -EINVAL;
}
/* replace trailing space by newline */
buf[len - 1] = '\n';
reg_val = data->meas_conf | (rate << HMC5843_RATE_OFFSET);
return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val);
return len;
}
static int hmc5843_check_sampling_frequency(struct hmc5843_data *data,
const char *buf)
static int hmc5843_check_int_plus_micros(const int (*vals)[2], int n,
int val, int val2)
{
const char * const *samp_freq = data->variant->regval_to_sample_freq;
int i;
for (i = 0; i < HMC5843_RATE_NOT_USED; i++) {
if (sysfs_streq(buf, samp_freq[i]))
for (i = 0; i < n; i++) {
if (val == vals[i][0] && val2 == vals[i][1])
return i;
}
return -EINVAL;
}
static ssize_t hmc5843_set_sampling_frequency(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
static ssize_t hmc5843_show_samp_freq_avail(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct hmc5843_data *data = iio_priv(indio_dev);
int rate;
return hmc5843_show_int_plus_micros(buf,
data->variant->regval_to_samp_freq, HMC5843_RATE_NOT_USED);
}
rate = hmc5843_check_sampling_frequency(data, buf);
if (rate < 0) {
dev_err(&client->dev,
"sampling frequency is not supported\n");
return rate;
}
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail);
mutex_lock(&data->lock);
dev_dbg(dev, "set rate to %d\n", rate);
if (hmc5843_set_rate(client, rate)) {
count = -EINVAL;
goto exit;
}
data->rate = rate;
static s32 hmc5843_set_rate(struct hmc5843_data *data, u8 rate)
{
u8 reg_val = data->meas_conf | (rate << HMC5843_RATE_OFFSET);
exit:
mutex_unlock(&data->lock);
return count;
return i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A,
reg_val);
}
static ssize_t hmc5843_show_sampling_frequency(struct device *dev,
struct device_attribute *attr, char *buf)
static int hmc5843_check_samp_freq(struct hmc5843_data *data,
int val, int val2)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct hmc5843_data *data = iio_priv(indio_dev);
s32 rate;
rate = i2c_smbus_read_byte_data(client, this_attr->address);
if (rate < 0)
return rate;
rate = (rate & HMC5843_RATE_BITMASK) >> HMC5843_RATE_OFFSET;
return sprintf(buf, "%s\n", data->variant->regval_to_sample_freq[rate]);
return hmc5843_check_int_plus_micros(
data->variant->regval_to_samp_freq, HMC5843_RATE_NOT_USED,
val, val2);
}
static IIO_DEVICE_ATTR(sampling_frequency,
S_IWUSR | S_IRUGO,
hmc5843_show_sampling_frequency,
hmc5843_set_sampling_frequency,
HMC5843_CONFIG_REG_A);
static ssize_t hmc5843_show_range_gain(struct device *dev,
struct device_attribute *attr,
char *buf)
......@@ -497,7 +430,6 @@ static ssize_t hmc5843_set_range_gain(struct device *dev,
size_t count)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct hmc5843_data *data = iio_priv(indio_dev);
unsigned long range = 0;
......@@ -518,7 +450,7 @@ static ssize_t hmc5843_set_range_gain(struct device *dev,
data->range = range;
range = range << HMC5843_RANGE_GAIN_OFFSET;
if (i2c_smbus_write_byte_data(client, this_attr->address, range))
if (i2c_smbus_write_byte_data(data->client, this_attr->address, range))
count = -EINVAL;
exit:
......@@ -534,31 +466,58 @@ static IIO_DEVICE_ATTR(in_magn_range,
static int hmc5843_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2,
long mask)
int *val, int *val2, long mask)
{
struct hmc5843_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
return hmc5843_read_measurement(indio_dev,
chan->address,
val);
return hmc5843_read_measurement(data, chan->address, val);
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = data->variant->regval_to_nanoscale[data->range];
return IIO_VAL_INT_PLUS_NANO;
case IIO_CHAN_INFO_SAMP_FREQ:
*val = data->variant->regval_to_samp_freq[data->rate][0];
*val2 = data->variant->regval_to_samp_freq[data->rate][1];
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static int hmc5843_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct hmc5843_data *data = iio_priv(indio_dev);
int ret, rate;
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
rate = hmc5843_check_samp_freq(data, val, val2);
if (rate < 0)
return -EINVAL;
mutex_lock(&data->lock);
ret = hmc5843_set_rate(data, rate);
if (ret >= 0)
data->rate = rate;
mutex_unlock(&data->lock);
return ret;
default:
return -EINVAL;
}
}
#define HMC5843_CHANNEL(axis, addr) \
{ \
.type = IIO_MAGN, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = addr \
}
......@@ -577,7 +536,6 @@ static const struct iio_chan_spec hmc5883_channels[] = {
static struct attribute *hmc5843_attributes[] = {
&iio_dev_attr_meas_conf.dev_attr.attr,
&iio_dev_attr_operating_mode.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_dev_attr_in_magn_range.dev_attr.attr,
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
NULL
......@@ -590,49 +548,40 @@ static const struct attribute_group hmc5843_group = {
static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
[HMC5843_ID] = {
.channels = hmc5843_channels,
.regval_to_sample_freq = hmc5843_regval_to_sample_freq,
.regval_to_samp_freq = hmc5843_regval_to_samp_freq,
.regval_to_input_field_mga =
hmc5843_regval_to_input_field_mga,
.regval_to_nanoscale = hmc5843_regval_to_nanoscale,
},
[HMC5883_ID] = {
.channels = hmc5883_channels,
.regval_to_sample_freq = hmc5883_regval_to_sample_freq,
.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
.regval_to_input_field_mga =
hmc5883_regval_to_input_field_mga,
.regval_to_nanoscale = hmc5883_regval_to_nanoscale,
},
[HMC5883L_ID] = {
.channels = hmc5883_channels,
.regval_to_sample_freq = hmc5883_regval_to_sample_freq,
.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
.regval_to_input_field_mga =
hmc5883l_regval_to_input_field_mga,
.regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
},
};
/* Called when we have found a new HMC58X3 */
static void hmc5843_init_client(struct i2c_client *client,
const struct i2c_device_id *id)
static void hmc5843_init(struct hmc5843_data *data)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct hmc5843_data *data = iio_priv(indio_dev);
data->variant = &hmc5843_chip_info_tbl[id->driver_data];
indio_dev->channels = data->variant->channels;
indio_dev->num_channels = 3;
hmc5843_set_meas_conf(client, data->meas_conf);
hmc5843_set_rate(client, data->rate);
hmc5843_configure(client, data->operating_mode);
i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_B, data->range);
mutex_init(&data->lock);
pr_info("%s initialized\n", id->name);
hmc5843_set_meas_conf(data, HMC5843_MEAS_CONF_NORMAL);
hmc5843_set_rate(data, HMC5843_RATE_DEFAULT);
hmc5843_configure(data->client, HMC5843_MODE_CONVERSION_CONTINUOUS);
i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_B,
HMC5843_RANGE_GAIN_DEFAULT);
}
static const struct iio_info hmc5843_info = {
.attrs = &hmc5843_group,
.read_raw = &hmc5843_read_raw,
.write_raw = &hmc5843_write_raw,
.driver_module = THIS_MODULE,
};
......@@ -649,17 +598,19 @@ static int hmc5843_probe(struct i2c_client *client,
/* default settings at probe */
data = iio_priv(indio_dev);
data->meas_conf = HMC5843_MEAS_CONF_NORMAL;
data->range = HMC5843_RANGE_GAIN_DEFAULT;
data->operating_mode = HMC5843_MODE_CONVERSION_CONTINUOUS;
data->client = client;
data->variant = &hmc5843_chip_info_tbl[id->driver_data];
mutex_init(&data->lock);
i2c_set_clientdata(client, indio_dev);
hmc5843_init_client(client, id);
indio_dev->info = &hmc5843_info;
indio_dev->name = id->name;
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = data->variant->channels;
indio_dev->num_channels = 3;
hmc5843_init(data);
err = iio_device_register(indio_dev);
if (err)
......@@ -687,10 +638,10 @@ static int hmc5843_suspend(struct device *dev)
static int hmc5843_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct hmc5843_data *data = iio_priv(i2c_get_clientdata(client));
struct hmc5843_data *data = iio_priv(i2c_get_clientdata(
to_i2c_client(dev)));
hmc5843_configure(client, data->operating_mode);
hmc5843_configure(data->client, data->operating_mode);
return 0;
}
......
......@@ -47,11 +47,13 @@ struct hid_sensor_hub_attribute_info {
* @hdev: Stores the hid instance.
* @vendor_id: Vendor id of hub device.
* @product_id: Product id of hub device.
* @ref_cnt: Number of MFD clients have opened this device
*/
struct hid_sensor_hub_device {
struct hid_device *hdev;
u32 vendor_id;
u32 product_id;
int ref_cnt;
};
/**
......@@ -74,6 +76,22 @@ struct hid_sensor_hub_callbacks {
void *priv);
};
/**
* sensor_hub_device_open() - Open hub device
* @hsdev: Hub device instance.
*
* Used to open hid device for sensor hub.
*/
int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev);
/**
* sensor_hub_device_clode() - Close hub device
* @hsdev: Hub device instance.
*
* Used to clode hid device for sensor hub.
*/
void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev);
/* Registration functions */
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment