mirror of https://gitee.com/openkylin/linux.git
Second set of IIO new device support features and cleanup for the 4.20 cycle.
One merge commit in here to bring in the SPI_CS_WORD flag patches that are also going via the SPI tree. There are a few more fixes than normal for a pull targetting the next merge window. These are all long term issues and as we are late in the cycle, they can wait. New device support * ad7606 - Add support fo the ad7605-4 driver. This driver is still in staging but is heading in the right direction to graduate, motivated partly by the requirement for this device support. * ST VL53L0X ToF ranging sensor - New minimal driver. Interrupt support to follow. New features * SPI_CS_WORD optimization allows long transfers with the chip select toggled every 16bits. There is a software fallback as well to let drivers not care about whether the hardware supports it. * bh1750 - Device tree support and bindings. * ti-ads7950 - Use the SPI_CS_WORD optmization to save lots of cpu cycles (assuming the hardware supports it) Fixes and cleanups * ad5064 - Fix some long incorrect regulator error handling that preventing enabling the internal regulator. * ad7606 - The ad7606 doesn't actually have a 2.5V range and the values provided for scale have always been wrong. Fix them. - Drop some wrong kernel-doc (things that don't exist) - Add missing kernel-doc * at91-adc - Fixing missing ack of dataready on sysfs channel reads to avoid spurious interrupts. - Fix a wrong channel numbers in triggered_buffer_mode * hmc5843 - Fix incorrect part number in a comment. * imx25-gcq - Fix a device_node leak in an error path. * meson-saradc - Drop an unused and pointless define. - Use of_device_get_match_data instead of opencoding - Tidy up how meson_sar_adc_param is accessed. - Rework prior to adding some temperature sensor support. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAluyb14RHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0Fogh+Q/9EwIO/feLfyoC5RfgDzbvPUTFzvEEFpoh HtlKRzKuQv03iWf0xb2XQPS0SBQSxldP0ugonBONENGR7mGf2vaF2cwrsPpe92JS 0jd64RND1mKmljsYb49ulm4wy2o5hAP2BH79sQku0ZwGlG8hhjgfdDo7Oz/PVwDL Mra9WXRhVXTfE3V8rF5rDpRtD7pjDNQlXsVfMg5C5sloh+d3ebTuFnJxyWExMv7d c1Hbh2JhJfDq0AmviTLdkQ8Sx8GpdFK8sYqkwcZUpMfrAutT/CL/zRDh4xOPe7+6 MRLfwd/w1zzsmaDWq+HiT70E2AVykKMhHbpJxLx/OPzibVsxOSRcm/y52M7kXqM2 nJFSu+qtoJO301nAycWzrrBaXGImuwtK9pt55Hi+3Ytc2xvJWA5QDnb1s6WV1xNY I2jA9QFaWjRhLgZBlluDhd5gGNPQaKj9EvGrBTC8mUDc6ybItZvKiwSV5+eMQZYV 4jbFAgDWDafMDl/7NYhyir5T8u8mjaUlSS2/SQUYq7+GzjKXSdY51M8yro369Vj+ P9X93ObkK2IntfbMSh8RfIFJFR7BlKQcHjOf8t5GPLvDnFPlTppgcV+1ZBrTp4RF V6UIOs5qZkXkR6/SIQl+e93i++LOmksVf1wMQ/WtfN7KhNdAYqaj2+W5SYWyYQMP v/z+KNuoeXw= =2Qke -----END PGP SIGNATURE----- Merge tag 'iio-for-4.20b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next Jonathan writes: Second set of IIO new device support features and cleanup for the 4.20 cycle. One merge commit in here to bring in the SPI_CS_WORD flag patches that are also going via the SPI tree. There are a few more fixes than normal for a pull targetting the next merge window. These are all long term issues and as we are late in the cycle, they can wait. New device support * ad7606 - Add support fo the ad7605-4 driver. This driver is still in staging but is heading in the right direction to graduate, motivated partly by the requirement for this device support. * ST VL53L0X ToF ranging sensor - New minimal driver. Interrupt support to follow. New features * SPI_CS_WORD optimization allows long transfers with the chip select toggled every 16bits. There is a software fallback as well to let drivers not care about whether the hardware supports it. * bh1750 - Device tree support and bindings. * ti-ads7950 - Use the SPI_CS_WORD optmization to save lots of cpu cycles (assuming the hardware supports it) Fixes and cleanups * ad5064 - Fix some long incorrect regulator error handling that preventing enabling the internal regulator. * ad7606 - The ad7606 doesn't actually have a 2.5V range and the values provided for scale have always been wrong. Fix them. - Drop some wrong kernel-doc (things that don't exist) - Add missing kernel-doc * at91-adc - Fixing missing ack of dataready on sysfs channel reads to avoid spurious interrupts. - Fix a wrong channel numbers in triggered_buffer_mode * hmc5843 - Fix incorrect part number in a comment. * imx25-gcq - Fix a device_node leak in an error path. * meson-saradc - Drop an unused and pointless define. - Use of_device_get_match_data instead of opencoding - Tidy up how meson_sar_adc_param is accessed. - Rework prior to adding some temperature sensor support. * tag 'iio-for-4.20b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: iio: ad5064: Fix regulator handling iio: adc: meson-saradc: use the address attribute from iio_chan_spec iio: adc: meson-saradc: do not use meson_sar_adc_iio_channels directly iio: adc: at91: fix wrong channel number in triggered buffer mode iio: adc: at91: fix acking DRDY irq on simple conversions iio: adc: meson-saradc: simplify access to meson_sar_adc_param iio: adc: meson-saradc: use of_device_get_match_data iio: adc: meson-saradc: remove #define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT iio: light: bh1750: Add device tree support dt-bindings: iio: light: bh1750: Add device tree binding documentation staging:iio:ad7606: Add support for the ad7605-4 iio: proximity: Add driver support for ST's VL53L0X ToF ranging sensor. staging:iio:ad7606: update structs with doc annotations iio: magnetometer: hmc5843: Fixed a comment error. iio: adc: imx25-gcq: Fix leak of device_node in mx25_gcq_setup_cfgs() iio: adc: ti-ads7950: use SPI_CS_WORD to reduce CPU usage spi: add software implementation for SPI_CS_WORD spi: add new SPI_CS_WORD flag staging:iio:ad7606: Remove incorrect kernel doc annotations staging:iio:ad7606: fix voltage scales
This commit is contained in:
commit
1c4ccab04a
|
@ -0,0 +1,18 @@
|
|||
ROHM BH1750 - ALS, Ambient light sensor
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Must be one of:
|
||||
"rohm,bh1710"
|
||||
"rohm,bh1715"
|
||||
"rohm,bh1721"
|
||||
"rohm,bh1750"
|
||||
"rohm,bh1751"
|
||||
- reg: the I2C address of the sensor
|
||||
|
||||
Example:
|
||||
|
||||
light-sensor@23 {
|
||||
compatible = "rohm,bh1750";
|
||||
reg = <0x23>;
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
ST VL53L0X ToF ranging sensor
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "st,vl53l0x"
|
||||
- reg: i2c address where to find the device
|
||||
|
||||
Example:
|
||||
|
||||
vl53l0x@29 {
|
||||
compatible = "st,vl53l0x";
|
||||
reg = <0x29>;
|
||||
};
|
|
@ -13772,6 +13772,13 @@ L: linux-i2c@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/i2c/busses/i2c-stm32*
|
||||
|
||||
ST VL53L0X ToF RANGER(I2C) IIO DRIVER
|
||||
M: Song Qiang <songqiang1304521@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/iio/proximity/vl53l0x-i2c.c
|
||||
F: Documentation/devicetree/bindings/iio/proximity/vl53l0x.txt
|
||||
|
||||
STABLE BRANCH
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
L: stable@vger.kernel.org
|
||||
|
|
|
@ -248,12 +248,14 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
|
|||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *idev = pf->indio_dev;
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
struct iio_chan_spec const *chan;
|
||||
int i, j = 0;
|
||||
|
||||
for (i = 0; i < idev->masklength; i++) {
|
||||
if (!test_bit(i, idev->active_scan_mask))
|
||||
continue;
|
||||
st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, i));
|
||||
chan = idev->channels + i;
|
||||
st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, chan->channel));
|
||||
j++;
|
||||
}
|
||||
|
||||
|
@ -279,6 +281,8 @@ static void handle_adc_eoc_trigger(int irq, struct iio_dev *idev)
|
|||
iio_trigger_poll(idev->trig);
|
||||
} else {
|
||||
st->last_value = at91_adc_readl(st, AT91_ADC_CHAN(st, st->chnb));
|
||||
/* Needed to ACK the DRDY interruption */
|
||||
at91_adc_readl(st, AT91_ADC_LCDR);
|
||||
st->done = true;
|
||||
wake_up_interruptible(&st->wq_data_avail);
|
||||
}
|
||||
|
|
|
@ -209,12 +209,14 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
|
|||
ret = of_property_read_u32(child, "reg", ®);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get reg property\n");
|
||||
of_node_put(child);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (reg >= MX25_NUM_CFGS) {
|
||||
dev_err(dev,
|
||||
"reg value is greater than the number of available configuration registers\n");
|
||||
of_node_put(child);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -228,6 +230,7 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
|
|||
if (IS_ERR(priv->vref[refp])) {
|
||||
dev_err(dev, "Error, trying to use external voltage reference without a vref-%s regulator.",
|
||||
mx25_gcq_refp_names[refp]);
|
||||
of_node_put(child);
|
||||
return PTR_ERR(priv->vref[refp]);
|
||||
}
|
||||
priv->channel_vref_mv[reg] =
|
||||
|
@ -240,6 +243,7 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
|
|||
break;
|
||||
default:
|
||||
dev_err(dev, "Invalid positive reference %d\n", refp);
|
||||
of_node_put(child);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -254,10 +258,12 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
|
|||
|
||||
if ((refp & MX25_ADCQ_CFG_REFP_MASK) != refp) {
|
||||
dev_err(dev, "Invalid fsl,adc-refp property value\n");
|
||||
of_node_put(child);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((refn & MX25_ADCQ_CFG_REFN_MASK) != refn) {
|
||||
dev_err(dev, "Invalid fsl,adc-refn property value\n");
|
||||
of_node_put(child);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,6 @@
|
|||
#define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26)
|
||||
#define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16)
|
||||
#define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15)
|
||||
#define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT 11
|
||||
#define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11)
|
||||
#define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10)
|
||||
#define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0)
|
||||
|
@ -173,6 +172,7 @@
|
|||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = _chan, \
|
||||
.address = _chan, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
|
@ -235,7 +235,7 @@ struct meson_sar_adc_data {
|
|||
struct meson_sar_adc_priv {
|
||||
struct regmap *regmap;
|
||||
struct regulator *vref;
|
||||
const struct meson_sar_adc_data *data;
|
||||
const struct meson_sar_adc_param *param;
|
||||
struct clk *clkin;
|
||||
struct clk *core_clk;
|
||||
struct clk *adc_sel_clk;
|
||||
|
@ -280,7 +280,7 @@ static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val)
|
|||
/* use val_calib = scale * val_raw + offset calibration function */
|
||||
tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias;
|
||||
|
||||
return clamp(tmp, 0, (1 << priv->data->param->resolution) - 1);
|
||||
return clamp(tmp, 0, (1 << priv->param->resolution) - 1);
|
||||
}
|
||||
|
||||
static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev)
|
||||
|
@ -324,15 +324,15 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
|
|||
|
||||
regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val);
|
||||
fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
|
||||
if (fifo_chan != chan->channel) {
|
||||
if (fifo_chan != chan->address) {
|
||||
dev_err(&indio_dev->dev,
|
||||
"ADC FIFO entry belongs to channel %d instead of %d\n",
|
||||
fifo_chan, chan->channel);
|
||||
"ADC FIFO entry belongs to channel %d instead of %lu\n",
|
||||
fifo_chan, chan->address);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval);
|
||||
fifo_val &= GENMASK(priv->data->param->resolution - 1, 0);
|
||||
fifo_val &= GENMASK(priv->param->resolution - 1, 0);
|
||||
*val = meson_sar_adc_calib_val(indio_dev, fifo_val);
|
||||
|
||||
return 0;
|
||||
|
@ -344,16 +344,16 @@ static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev,
|
|||
enum meson_sar_adc_num_samples samples)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
int val, channel = chan->channel;
|
||||
int val, address = chan->address;
|
||||
|
||||
val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(channel);
|
||||
val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(address);
|
||||
regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL,
|
||||
MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(channel),
|
||||
MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(address),
|
||||
val);
|
||||
|
||||
val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(channel);
|
||||
val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(address);
|
||||
regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL,
|
||||
MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(channel), val);
|
||||
MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(address), val);
|
||||
}
|
||||
|
||||
static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev,
|
||||
|
@ -373,23 +373,23 @@ static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev,
|
|||
|
||||
/* map channel index 0 to the channel which we want to read */
|
||||
regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0),
|
||||
chan->channel);
|
||||
chan->address);
|
||||
regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST,
|
||||
MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval);
|
||||
|
||||
regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK,
|
||||
chan->channel);
|
||||
chan->address);
|
||||
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW,
|
||||
MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK,
|
||||
regval);
|
||||
|
||||
regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK,
|
||||
chan->channel);
|
||||
chan->address);
|
||||
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW,
|
||||
MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK,
|
||||
regval);
|
||||
|
||||
if (chan->channel == 6)
|
||||
if (chan->address == 6)
|
||||
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
|
||||
MESON_SAR_ADC_DELTA_10_TEMP_SEL, 0);
|
||||
}
|
||||
|
@ -451,7 +451,7 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev)
|
|||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
|
||||
if (priv->data->param->has_bl30_integration) {
|
||||
if (priv->param->has_bl30_integration) {
|
||||
/* prevent BL30 from using the SAR ADC while we are using it */
|
||||
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
|
||||
MESON_SAR_ADC_DELAY_KERNEL_BUSY,
|
||||
|
@ -479,7 +479,7 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
|
|||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
|
||||
if (priv->data->param->has_bl30_integration)
|
||||
if (priv->param->has_bl30_integration)
|
||||
/* allow BL30 to use the SAR ADC again */
|
||||
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
|
||||
MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
|
||||
|
@ -527,8 +527,8 @@ static int meson_sar_adc_get_sample(struct iio_dev *indio_dev,
|
|||
|
||||
if (ret) {
|
||||
dev_warn(indio_dev->dev.parent,
|
||||
"failed to read sample for channel %d: %d\n",
|
||||
chan->channel, ret);
|
||||
"failed to read sample for channel %lu: %d\n",
|
||||
chan->address, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -563,7 +563,7 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
*val = ret / 1000;
|
||||
*val2 = priv->data->param->resolution;
|
||||
*val2 = priv->param->resolution;
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
|
||||
case IIO_CHAN_INFO_CALIBBIAS:
|
||||
|
@ -636,7 +636,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
|
|||
*/
|
||||
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
|
||||
|
||||
if (priv->data->param->has_bl30_integration) {
|
||||
if (priv->param->has_bl30_integration) {
|
||||
/*
|
||||
* leave sampling delay and the input clocks as configured by
|
||||
* BL30 to make sure BL30 gets the values it expects when
|
||||
|
@ -716,7 +716,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(priv->adc_clk, priv->data->param->clock_rate);
|
||||
ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate);
|
||||
if (ret) {
|
||||
dev_err(indio_dev->dev.parent,
|
||||
"failed to set adc clock rate\n");
|
||||
|
@ -729,7 +729,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
|
|||
static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
const struct meson_sar_adc_param *param = priv->data->param;
|
||||
const struct meson_sar_adc_param *param = priv->param;
|
||||
u32 enable_mask;
|
||||
|
||||
if (param->bandgap_reg == MESON_SAR_ADC_REG11)
|
||||
|
@ -849,13 +849,13 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev)
|
|||
int ret, nominal0, nominal1, value0, value1;
|
||||
|
||||
/* use points 25% and 75% for calibration */
|
||||
nominal0 = (1 << priv->data->param->resolution) / 4;
|
||||
nominal1 = (1 << priv->data->param->resolution) * 3 / 4;
|
||||
nominal0 = (1 << priv->param->resolution) / 4;
|
||||
nominal1 = (1 << priv->param->resolution) * 3 / 4;
|
||||
|
||||
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4);
|
||||
usleep_range(10, 20);
|
||||
ret = meson_sar_adc_get_sample(indio_dev,
|
||||
&meson_sar_adc_iio_channels[7],
|
||||
&indio_dev->channels[7],
|
||||
MEAN_AVERAGING, EIGHT_SAMPLES, &value0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -863,7 +863,7 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev)
|
|||
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4);
|
||||
usleep_range(10, 20);
|
||||
ret = meson_sar_adc_get_sample(indio_dev,
|
||||
&meson_sar_adc_iio_channels[7],
|
||||
&indio_dev->channels[7],
|
||||
MEAN_AVERAGING, EIGHT_SAMPLES, &value1);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -979,11 +979,11 @@ MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match);
|
|||
|
||||
static int meson_sar_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct meson_sar_adc_data *match_data;
|
||||
struct meson_sar_adc_priv *priv;
|
||||
struct iio_dev *indio_dev;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
const struct of_device_id *match;
|
||||
int irq, ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
|
||||
|
@ -995,15 +995,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
|||
priv = iio_priv(indio_dev);
|
||||
init_completion(&priv->done);
|
||||
|
||||
match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
|
||||
if (!match) {
|
||||
dev_err(&pdev->dev, "failed to match device\n");
|
||||
match_data = of_device_get_match_data(&pdev->dev);
|
||||
if (!match_data) {
|
||||
dev_err(&pdev->dev, "failed to get match data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv->data = match->data;
|
||||
priv->param = match_data->param;
|
||||
|
||||
indio_dev->name = priv->data->name;
|
||||
indio_dev->name = match_data->name;
|
||||
indio_dev->dev.parent = &pdev->dev;
|
||||
indio_dev->dev.of_node = pdev->dev.of_node;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
@ -1027,7 +1027,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
|
||||
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
priv->data->param->regmap_config);
|
||||
priv->param->regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
return PTR_ERR(priv->regmap);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
|
||||
struct ti_ads7950_state {
|
||||
struct spi_device *spi;
|
||||
struct spi_transfer ring_xfer[TI_ADS7950_MAX_CHAN + 2];
|
||||
struct spi_transfer ring_xfer;
|
||||
struct spi_transfer scan_single_xfer[3];
|
||||
struct spi_message ring_msg;
|
||||
struct spi_message scan_single_msg;
|
||||
|
@ -65,11 +65,11 @@ struct ti_ads7950_state {
|
|||
* DMA (thus cache coherency maintenance) requires the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
__be16 rx_buf[TI_ADS7950_MAX_CHAN + TI_ADS7950_TIMESTAMP_SIZE]
|
||||
u16 rx_buf[TI_ADS7950_MAX_CHAN + 2 + TI_ADS7950_TIMESTAMP_SIZE]
|
||||
____cacheline_aligned;
|
||||
__be16 tx_buf[TI_ADS7950_MAX_CHAN];
|
||||
__be16 single_tx;
|
||||
__be16 single_rx;
|
||||
u16 tx_buf[TI_ADS7950_MAX_CHAN + 2];
|
||||
u16 single_tx;
|
||||
u16 single_rx;
|
||||
|
||||
};
|
||||
|
||||
|
@ -108,7 +108,7 @@ enum ti_ads7950_id {
|
|||
.realbits = bits, \
|
||||
.storagebits = 16, \
|
||||
.shift = 12 - (bits), \
|
||||
.endianness = IIO_BE, \
|
||||
.endianness = IIO_CPU, \
|
||||
}, \
|
||||
}
|
||||
|
||||
|
@ -249,23 +249,14 @@ static int ti_ads7950_update_scan_mode(struct iio_dev *indio_dev,
|
|||
len = 0;
|
||||
for_each_set_bit(i, active_scan_mask, indio_dev->num_channels) {
|
||||
cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(i) | st->settings;
|
||||
st->tx_buf[len++] = cpu_to_be16(cmd);
|
||||
st->tx_buf[len++] = cmd;
|
||||
}
|
||||
|
||||
/* Data for the 1st channel is not returned until the 3rd transfer */
|
||||
len += 2;
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i + 2) < len)
|
||||
st->ring_xfer[i].tx_buf = &st->tx_buf[i];
|
||||
if (i >= 2)
|
||||
st->ring_xfer[i].rx_buf = &st->rx_buf[i - 2];
|
||||
st->ring_xfer[i].len = 2;
|
||||
st->ring_xfer[i].cs_change = 1;
|
||||
}
|
||||
/* make sure last transfer's cs_change is not set */
|
||||
st->ring_xfer[len - 1].cs_change = 0;
|
||||
st->tx_buf[len++] = 0;
|
||||
st->tx_buf[len++] = 0;
|
||||
|
||||
spi_message_init_with_transfers(&st->ring_msg, st->ring_xfer, len);
|
||||
st->ring_xfer.len = len * 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -281,7 +272,7 @@ static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p)
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &st->rx_buf[2],
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
out:
|
||||
|
@ -298,13 +289,13 @@ static int ti_ads7950_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
|
|||
mutex_lock(&indio_dev->mlock);
|
||||
|
||||
cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(ch) | st->settings;
|
||||
st->single_tx = cpu_to_be16(cmd);
|
||||
st->single_tx = cmd;
|
||||
|
||||
ret = spi_sync(st->spi, &st->scan_single_msg);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = be16_to_cpu(st->single_rx);
|
||||
ret = st->single_rx;
|
||||
|
||||
out:
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
@ -378,6 +369,14 @@ static int ti_ads7950_probe(struct spi_device *spi)
|
|||
const struct ti_ads7950_chip_info *info;
|
||||
int ret;
|
||||
|
||||
spi->bits_per_word = 16;
|
||||
spi->mode |= SPI_CS_WORD;
|
||||
ret = spi_setup(spi);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "Error in spi setup\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
@ -398,6 +397,16 @@ static int ti_ads7950_probe(struct spi_device *spi)
|
|||
indio_dev->num_channels = info->num_channels;
|
||||
indio_dev->info = &ti_ads7950_info;
|
||||
|
||||
/* build spi ring message */
|
||||
spi_message_init(&st->ring_msg);
|
||||
|
||||
st->ring_xfer.tx_buf = &st->tx_buf[0];
|
||||
st->ring_xfer.rx_buf = &st->rx_buf[0];
|
||||
/* len will be set later */
|
||||
st->ring_xfer.cs_change = true;
|
||||
|
||||
spi_message_add_tail(&st->ring_xfer, &st->ring_msg);
|
||||
|
||||
/*
|
||||
* Setup default message. The sample is read at the end of the first
|
||||
* transfer, then it takes one full cycle to convert the sample and one
|
||||
|
|
|
@ -808,6 +808,40 @@ static int ad5064_set_config(struct ad5064_state *st, unsigned int val)
|
|||
return ad5064_write(st, cmd, 0, val, 0);
|
||||
}
|
||||
|
||||
static int ad5064_request_vref(struct ad5064_state *st, struct device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < ad5064_num_vref(st); ++i)
|
||||
st->vref_reg[i].supply = ad5064_vref_name(st, i);
|
||||
|
||||
if (!st->chip_info->internal_vref)
|
||||
return devm_regulator_bulk_get(dev, ad5064_num_vref(st),
|
||||
st->vref_reg);
|
||||
|
||||
/*
|
||||
* This assumes that when the regulator has an internal VREF
|
||||
* there is only one external VREF connection, which is
|
||||
* currently the case for all supported devices.
|
||||
*/
|
||||
st->vref_reg[0].consumer = devm_regulator_get_optional(dev, "vref");
|
||||
if (!IS_ERR(st->vref_reg[0].consumer))
|
||||
return 0;
|
||||
|
||||
ret = PTR_ERR(st->vref_reg[0].consumer);
|
||||
if (ret != -ENODEV)
|
||||
return ret;
|
||||
|
||||
/* If no external regulator was supplied use the internal VREF */
|
||||
st->use_internal_vref = true;
|
||||
ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to enable internal vref: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad5064_probe(struct device *dev, enum ad5064_type type,
|
||||
const char *name, ad5064_write_func write)
|
||||
{
|
||||
|
@ -828,22 +862,11 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
|
|||
st->dev = dev;
|
||||
st->write = write;
|
||||
|
||||
for (i = 0; i < ad5064_num_vref(st); ++i)
|
||||
st->vref_reg[i].supply = ad5064_vref_name(st, i);
|
||||
ret = ad5064_request_vref(st, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ad5064_num_vref(st),
|
||||
st->vref_reg);
|
||||
if (ret) {
|
||||
if (!st->chip_info->internal_vref)
|
||||
return ret;
|
||||
st->use_internal_vref = true;
|
||||
ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable internal vref: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
if (!st->use_internal_vref) {
|
||||
ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -307,9 +307,20 @@ static const struct i2c_device_id bh1750_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bh1750_id);
|
||||
|
||||
static const struct of_device_id bh1750_of_match[] = {
|
||||
{ .compatible = "rohm,bh1710", },
|
||||
{ .compatible = "rohm,bh1715", },
|
||||
{ .compatible = "rohm,bh1721", },
|
||||
{ .compatible = "rohm,bh1750", },
|
||||
{ .compatible = "rohm,bh1751", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bh1750_of_match);
|
||||
|
||||
static struct i2c_driver bh1750_driver = {
|
||||
.driver = {
|
||||
.name = "bh1750",
|
||||
.of_match_table = bh1750_of_match,
|
||||
.pm = &bh1750_pm_ops,
|
||||
},
|
||||
.probe = bh1750_probe,
|
||||
|
|
|
@ -31,7 +31,7 @@ enum hmc5843_ids {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct hcm5843_data - device specific data
|
||||
* struct hmc5843_data - device specific data
|
||||
* @dev: actual device
|
||||
* @lock: update and read regmap data
|
||||
* @regmap: hardware access register maps
|
||||
|
|
|
@ -92,4 +92,15 @@ config SRF08
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called srf08.
|
||||
|
||||
config VL53L0X_I2C
|
||||
tristate "STMicroelectronics VL53L0X ToF ranger sensor (I2C)"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here to build a driver for STMicroelectronics VL53L0X
|
||||
ToF ranger sensors with i2c interface.
|
||||
This driver can be used to measure the distance of objects.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vl53l0x-i2c.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -11,3 +11,5 @@ obj-$(CONFIG_RFD77402) += rfd77402.o
|
|||
obj-$(CONFIG_SRF04) += srf04.o
|
||||
obj-$(CONFIG_SRF08) += srf08.o
|
||||
obj-$(CONFIG_SX9500) += sx9500.o
|
||||
obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o
|
||||
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Support for ST VL53L0X FlightSense ToF Ranging Sensor on a i2c bus.
|
||||
*
|
||||
* Copyright (C) 2016 STMicroelectronics Imaging Division.
|
||||
* Copyright (C) 2018 Song Qiang <songqiang1304521@gmail.com>
|
||||
*
|
||||
* Datasheet available at
|
||||
* <https://www.st.com/resource/en/datasheet/vl53l0x.pdf>
|
||||
*
|
||||
* Default 7-bit i2c slave address 0x29.
|
||||
*
|
||||
* TODO: FIFO buffer, continuous mode, interrupts, range selection,
|
||||
* sensor ID check.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
|
||||
#define VL_REG_SYSRANGE_START 0x00
|
||||
|
||||
#define VL_REG_SYSRANGE_MODE_MASK GENMASK(3, 0)
|
||||
#define VL_REG_SYSRANGE_MODE_SINGLESHOT 0x00
|
||||
#define VL_REG_SYSRANGE_MODE_START_STOP BIT(0)
|
||||
#define VL_REG_SYSRANGE_MODE_BACKTOBACK BIT(1)
|
||||
#define VL_REG_SYSRANGE_MODE_TIMED BIT(2)
|
||||
#define VL_REG_SYSRANGE_MODE_HISTOGRAM BIT(3)
|
||||
|
||||
#define VL_REG_RESULT_INT_STATUS 0x13
|
||||
#define VL_REG_RESULT_RANGE_STATUS 0x14
|
||||
#define VL_REG_RESULT_RANGE_STATUS_COMPLETE BIT(0)
|
||||
|
||||
struct vl53l0x_data {
|
||||
struct i2c_client *client;
|
||||
};
|
||||
|
||||
static int vl53l0x_read_proximity(struct vl53l0x_data *data,
|
||||
const struct iio_chan_spec *chan,
|
||||
int *val)
|
||||
{
|
||||
struct i2c_client *client = data->client;
|
||||
u16 tries = 20;
|
||||
u8 buffer[12];
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, VL_REG_SYSRANGE_START, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
do {
|
||||
ret = i2c_smbus_read_byte_data(client,
|
||||
VL_REG_RESULT_RANGE_STATUS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret & VL_REG_RESULT_RANGE_STATUS_COMPLETE)
|
||||
break;
|
||||
|
||||
usleep_range(1000, 5000);
|
||||
} while (--tries);
|
||||
if (!tries)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
ret = i2c_smbus_read_i2c_block_data(client, VL_REG_RESULT_RANGE_STATUS,
|
||||
12, buffer);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret != 12)
|
||||
return -EREMOTEIO;
|
||||
|
||||
/* Values should be between 30~1200 in millimeters. */
|
||||
*val = (buffer[10] << 8) + buffer[11];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec vl53l0x_channels[] = {
|
||||
{
|
||||
.type = IIO_DISTANCE,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
},
|
||||
};
|
||||
|
||||
static int vl53l0x_read_raw(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct vl53l0x_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
if (chan->type != IIO_DISTANCE)
|
||||
return -EINVAL;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
ret = vl53l0x_read_proximity(data, chan, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = 0;
|
||||
*val2 = 1000;
|
||||
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct iio_info vl53l0x_info = {
|
||||
.read_raw = vl53l0x_read_raw,
|
||||
};
|
||||
|
||||
static int vl53l0x_probe(struct i2c_client *client)
|
||||
{
|
||||
struct vl53l0x_data *data;
|
||||
struct iio_dev *indio_dev;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
data->client = client;
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_I2C_BLOCK |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->name = "vl53l0x";
|
||||
indio_dev->info = &vl53l0x_info;
|
||||
indio_dev->channels = vl53l0x_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(vl53l0x_channels);
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
return devm_iio_device_register(&client->dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id st_vl53l0x_dt_match[] = {
|
||||
{ .compatible = "st,vl53l0x", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, st_vl53l0x_dt_match);
|
||||
|
||||
static struct i2c_driver vl53l0x_driver = {
|
||||
.driver = {
|
||||
.name = "vl53l0x-i2c",
|
||||
.of_match_table = st_vl53l0x_dt_match,
|
||||
},
|
||||
.probe_new = vl53l0x_probe,
|
||||
};
|
||||
module_i2c_driver(vl53l0x_driver);
|
||||
|
||||
MODULE_AUTHOR("Song Qiang <songqiang1304521@gmail.com>");
|
||||
MODULE_DESCRIPTION("ST vl53l0x ToF ranging sensor driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -2774,8 +2774,10 @@ int spi_setup(struct spi_device *spi)
|
|||
return -EINVAL;
|
||||
/* help drivers fail *cleanly* when they need options
|
||||
* that aren't supported with their current controller
|
||||
* SPI_CS_WORD has a fallback software implementation,
|
||||
* so it is ignored here.
|
||||
*/
|
||||
bad_bits = spi->mode & ~spi->controller->mode_bits;
|
||||
bad_bits = spi->mode & ~(spi->controller->mode_bits | SPI_CS_WORD);
|
||||
ugly_bits = bad_bits &
|
||||
(SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD);
|
||||
if (ugly_bits) {
|
||||
|
@ -2829,6 +2831,33 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
|
|||
if (list_empty(&message->transfers))
|
||||
return -EINVAL;
|
||||
|
||||
/* If an SPI controller does not support toggling the CS line on each
|
||||
* transfer (indicated by the SPI_CS_WORD flag), we can emulate it by
|
||||
* splitting transfers into one-word transfers and ensuring that
|
||||
* cs_change is set for each transfer.
|
||||
*/
|
||||
if ((spi->mode & SPI_CS_WORD) && !(ctlr->mode_bits & SPI_CS_WORD)) {
|
||||
size_t maxsize;
|
||||
int ret;
|
||||
|
||||
maxsize = (spi->bits_per_word + 7) / 8;
|
||||
|
||||
/* spi_split_transfers_maxsize() requires message->spi */
|
||||
message->spi = spi;
|
||||
|
||||
ret = spi_split_transfers_maxsize(ctlr, message, maxsize,
|
||||
GFP_KERNEL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(xfer, &message->transfers, transfer_list) {
|
||||
/* don't change cs_change on the last entry in the list */
|
||||
if (list_is_last(&xfer->transfer_list, &message->transfers))
|
||||
break;
|
||||
xfer->cs_change = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Half-duplex links include original MicroWire, and ones with
|
||||
* only one data pin like SPI_3WIRE (switches direction) or where
|
||||
* either MOSI or MISO is missing. They can also be caused by
|
||||
|
|
|
@ -11,7 +11,7 @@ config AD7606
|
|||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say yes here to build support for Analog Devices:
|
||||
ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
|
||||
ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7606.
|
||||
|
|
|
@ -26,9 +26,12 @@
|
|||
|
||||
#include "ad7606.h"
|
||||
|
||||
/* Scales are computed as 2.5/2**16 and 5/2**16 respectively */
|
||||
/*
|
||||
* Scales are computed as 5000/32768 and 10000/32768 respectively,
|
||||
* so that when applied to the raw values they provide mV values
|
||||
*/
|
||||
static const unsigned int scale_avail[2][2] = {
|
||||
{0, 38147}, {0, 76294}
|
||||
{0, 152588}, {0, 305176}
|
||||
};
|
||||
|
||||
static int ad7606_reset(struct ad7606_state *st)
|
||||
|
@ -273,7 +276,7 @@ static const struct attribute_group ad7606_attribute_group_range = {
|
|||
.attrs = ad7606_attributes_range,
|
||||
};
|
||||
|
||||
#define AD7606_CHANNEL(num) \
|
||||
#define AD760X_CHANNEL(num, mask) \
|
||||
{ \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
|
@ -281,8 +284,7 @@ static const struct attribute_group ad7606_attribute_group_range = {
|
|||
.address = num, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
|
||||
.info_mask_shared_by_all = \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
.info_mask_shared_by_all = mask, \
|
||||
.scan_index = num, \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
|
@ -292,6 +294,20 @@ static const struct attribute_group ad7606_attribute_group_range = {
|
|||
}, \
|
||||
}
|
||||
|
||||
#define AD7605_CHANNEL(num) \
|
||||
AD760X_CHANNEL(num, 0)
|
||||
|
||||
#define AD7606_CHANNEL(num) \
|
||||
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
|
||||
|
||||
static const struct iio_chan_spec ad7605_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(4),
|
||||
AD7605_CHANNEL(0),
|
||||
AD7605_CHANNEL(1),
|
||||
AD7605_CHANNEL(2),
|
||||
AD7605_CHANNEL(3),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7606_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(8),
|
||||
AD7606_CHANNEL(0),
|
||||
|
@ -308,17 +324,24 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = {
|
|||
/*
|
||||
* More devices added in future
|
||||
*/
|
||||
[ID_AD7605_4] = {
|
||||
.channels = ad7605_channels,
|
||||
.num_channels = 5,
|
||||
},
|
||||
[ID_AD7606_8] = {
|
||||
.channels = ad7606_channels,
|
||||
.num_channels = 9,
|
||||
.has_oversampling = true,
|
||||
},
|
||||
[ID_AD7606_6] = {
|
||||
.channels = ad7606_channels,
|
||||
.num_channels = 7,
|
||||
.has_oversampling = true,
|
||||
},
|
||||
[ID_AD7606_4] = {
|
||||
.channels = ad7606_channels,
|
||||
.num_channels = 5,
|
||||
.has_oversampling = true,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -349,6 +372,9 @@ static int ad7606_request_gpios(struct ad7606_state *st)
|
|||
if (IS_ERR(st->gpio_frstdata))
|
||||
return PTR_ERR(st->gpio_frstdata);
|
||||
|
||||
if (!st->chip_info->has_oversampling)
|
||||
return 0;
|
||||
|
||||
st->gpio_os = devm_gpiod_get_array_optional(dev, "oversampling-ratio",
|
||||
GPIOD_OUT_LOW);
|
||||
return PTR_ERR_OR_ZERO(st->gpio_os);
|
||||
|
@ -427,12 +453,12 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
|||
return ret;
|
||||
}
|
||||
|
||||
st->chip_info = &ad7606_chip_info_tbl[id];
|
||||
|
||||
ret = ad7606_request_gpios(st);
|
||||
if (ret)
|
||||
goto error_disable_reg;
|
||||
|
||||
st->chip_info = &ad7606_chip_info_tbl[id];
|
||||
|
||||
indio_dev->dev.parent = dev;
|
||||
if (st->gpio_os) {
|
||||
if (st->gpio_range)
|
||||
|
|
|
@ -11,20 +11,40 @@
|
|||
|
||||
/**
|
||||
* struct ad7606_chip_info - chip specific information
|
||||
* @name: identification string for chip
|
||||
* @channels: channel specification
|
||||
* @num_channels: number of channels
|
||||
* @lock protect sensor state
|
||||
* @has_oversampling: whether the device has oversampling support
|
||||
*/
|
||||
|
||||
struct ad7606_chip_info {
|
||||
const struct iio_chan_spec *channels;
|
||||
unsigned int num_channels;
|
||||
bool has_oversampling;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ad7606_state - driver instance specific data
|
||||
* @lock protect sensor state
|
||||
* @dev pointer to kernel device
|
||||
* @chip_info entry in the table of chips that describes this device
|
||||
* @reg regulator info for the the power supply of the device
|
||||
* @poll_work work struct for continuously reading data from the device
|
||||
* into an IIO triggered buffer
|
||||
* @wq_data_avail wait queue struct for buffer mode
|
||||
* @bops bus operations (SPI or parallel)
|
||||
* @range voltage range selection, selects which scale to apply
|
||||
* @oversampling oversampling selection
|
||||
* @done marks whether reading data is done
|
||||
* @base_address address from where to read data in parallel operation
|
||||
* @lock protect sensor state from concurrent accesses to GPIOs
|
||||
* @gpio_convst GPIO descriptor for conversion start signal (CONVST)
|
||||
* @gpio_reset GPIO descriptor for device hard-reset
|
||||
* @gpio_range GPIO descriptor for range selection
|
||||
* @gpio_standby GPIO descriptor for stand-by signal (STBY),
|
||||
* controls power-down mode of device
|
||||
* @gpio_frstdata GPIO descriptor for reading from device when data
|
||||
* is being read on the first channel
|
||||
* @gpio_os GPIO descriptors to control oversampling on the device
|
||||
* @data buffer for reading data from the device
|
||||
*/
|
||||
|
||||
struct ad7606_state {
|
||||
|
@ -55,6 +75,10 @@ struct ad7606_state {
|
|||
unsigned short data[12] ____cacheline_aligned;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ad7606_bus_ops - driver bus operations
|
||||
* @read_block function pointer for reading blocks of data
|
||||
*/
|
||||
struct ad7606_bus_ops {
|
||||
/* more methods added in future? */
|
||||
int (*read_block)(struct device *dev, int num, void *data);
|
||||
|
@ -66,6 +90,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
|||
int ad7606_remove(struct device *dev, int irq);
|
||||
|
||||
enum ad7606_supported_device_ids {
|
||||
ID_AD7605_4,
|
||||
ID_AD7606_8,
|
||||
ID_AD7606_6,
|
||||
ID_AD7606_4
|
||||
|
|
|
@ -79,6 +79,9 @@ static int ad7606_par_remove(struct platform_device *pdev)
|
|||
|
||||
static const struct platform_device_id ad7606_driver_ids[] = {
|
||||
{
|
||||
.name = "ad7605-4",
|
||||
.driver_data = ID_AD7605_4,
|
||||
}, {
|
||||
.name = "ad7606-8",
|
||||
.driver_data = ID_AD7606_8,
|
||||
}, {
|
||||
|
|
|
@ -55,6 +55,7 @@ static int ad7606_spi_remove(struct spi_device *spi)
|
|||
}
|
||||
|
||||
static const struct spi_device_id ad7606_id[] = {
|
||||
{"ad7605-4", ID_AD7605_4},
|
||||
{"ad7606-8", ID_AD7606_8},
|
||||
{"ad7606-6", ID_AD7606_6},
|
||||
{"ad7606-4", ID_AD7606_4},
|
||||
|
|
|
@ -163,6 +163,7 @@ struct spi_device {
|
|||
#define SPI_TX_QUAD 0x200 /* transmit with 4 wires */
|
||||
#define SPI_RX_DUAL 0x400 /* receive with 2 wires */
|
||||
#define SPI_RX_QUAD 0x800 /* receive with 4 wires */
|
||||
#define SPI_CS_WORD 0x1000 /* toggle cs after each word */
|
||||
int irq;
|
||||
void *controller_state;
|
||||
void *controller_data;
|
||||
|
@ -177,7 +178,6 @@ struct spi_device {
|
|||
* the controller talks to each chip, like:
|
||||
* - memory packing (12 bit samples into low bits, others zeroed)
|
||||
* - priority
|
||||
* - drop chipselect after each word
|
||||
* - chipselect delays
|
||||
* - ...
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue