mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'char-misc-7.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc/iio fixes from Greg KH: "Here are some small char/misc/iio driver fixes for 7.1-rc6. Included in here are: - lots of small IIO driver fixes for reported problems. - Android binder bugfixes for reported issues. - small comedi test driver fixes - counter driver fix - parport driver fix (people still use this?) - rpi driver fix - uio driver fix All of these have been in linux-next for over a week with no reported problems" * tag 'char-misc-7.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (41 commits) Revert "gpib: cb7210: Fix region leak when request_irq fails" misc: rp1: Send IACK on IRQ activate to fix kdump/kexec gpib: cb7210: Fix region leak when request_irq fails parport: Fix race between port and client registration uio: uio_pci_generic_sva: fix double free of devm_kzalloc() memory rust_binder: Avoid holding lock when dropping delivered_death rust_binder: avoid calling pending_oneway_finished() on TF_UPDATE_TXN comedi: comedi_test: fix check for valid scan_begin_src in waveform_ai_cmdtest() comedi: comedi_test: Fix limiting of convert_arg in waveform_ai_cmdtest() iio: adc: viperboard: Fix error handling in vprbrd_iio_read_raw iio: gyro: itg3200: fix i2c read into the wrong stack location iio: dac: ad5686: fix powerdown control on dual-channel devices iio: dac: ad5686: acquire lock when doing powerdown control iio: temperature: tsys01: fix broken PROM checksum validation iio: dac: ad3530r: Fix AD3531/AD3531R powerdown mode strings iio: buffer: hw-consumer: fix use-after-free in error path iio: dac: ad5686: fix input raw value check iio: dac: ad5686: fix ref bit initialization for single-channel parts iio: ssp_sensors: cancel delayed work_refresh on remove iio: adc: meson-saradc: fix calibration buffer leak on error ...
This commit is contained in:
@@ -157,6 +157,14 @@ impl Allocation {
|
||||
self.get_or_init_info().target_node = Some(target_node);
|
||||
}
|
||||
|
||||
pub(crate) fn take_oneway_node(&mut self) -> Option<DArc<Node>> {
|
||||
if let Some(info) = self.allocation_info.as_mut() {
|
||||
info.oneway_node.take()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Reserve enough space to push at least `num_fds` fds.
|
||||
pub(crate) fn info_add_fd_reserve(&mut self, num_fds: usize) -> Result {
|
||||
self.get_or_init_info()
|
||||
|
||||
@@ -1402,7 +1402,12 @@ impl Process {
|
||||
// Clear delivered_deaths list.
|
||||
//
|
||||
// Scope ensures that MutexGuard is dropped while executing the body.
|
||||
while let Some(delivered_death) = { self.inner.lock().delivered_deaths.pop_front() } {
|
||||
while let Some(delivered_death) = {
|
||||
// Explicitly bind to avoid tail expression lifetime extension of the lockguard
|
||||
// Can be removed when the kernel moves to edition 2024
|
||||
let maybe_death = self.inner.lock().delivered_deaths.pop_front();
|
||||
maybe_death
|
||||
} {
|
||||
drop(delivered_death);
|
||||
}
|
||||
|
||||
|
||||
@@ -270,7 +270,8 @@ impl Transaction {
|
||||
/// Not used for replies.
|
||||
pub(crate) fn submit(self: DLArc<Self>, info: &mut TransactionInfo) -> BinderResult {
|
||||
// Defined before `process_inner` so that the destructor runs after releasing the lock.
|
||||
let mut _t_outdated;
|
||||
let _t_outdated;
|
||||
let _oneway_node;
|
||||
|
||||
let oneway = self.flags & TF_ONE_WAY != 0;
|
||||
let process = self.to.clone();
|
||||
@@ -287,6 +288,14 @@ impl Transaction {
|
||||
if let Some(t_outdated) =
|
||||
target_node.take_outdated_transaction(&self, &mut process_inner)
|
||||
{
|
||||
let mut alloc_guard = t_outdated.allocation.lock();
|
||||
if let Some(alloc) = (*alloc_guard).as_mut() {
|
||||
// Take the oneway node to prevent `Allocation::drop` from calling
|
||||
// `pending_oneway_finished()`, which would be incorrect as this
|
||||
// transaction is not being submitted.
|
||||
_oneway_node = alloc.take_oneway_node();
|
||||
}
|
||||
drop(alloc_guard);
|
||||
// Save the transaction to be dropped after locks are released.
|
||||
_t_outdated = t_outdated;
|
||||
}
|
||||
|
||||
@@ -274,6 +274,7 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
|
||||
/* Step 2a : make sure trigger sources are unique */
|
||||
|
||||
err |= comedi_check_trigger_is_unique(cmd->convert_src);
|
||||
err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
|
||||
err |= comedi_check_trigger_is_unique(cmd->stop_src);
|
||||
|
||||
/* Step 2b : and mutually compatible */
|
||||
@@ -324,10 +325,10 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
|
||||
arg = min(arg,
|
||||
rounddown(UINT_MAX, (unsigned int)NSEC_PER_USEC));
|
||||
arg = NSEC_PER_USEC * DIV_ROUND_CLOSEST(arg, NSEC_PER_USEC);
|
||||
if (cmd->scan_begin_arg == TRIG_TIMER) {
|
||||
if (cmd->scan_begin_src == TRIG_TIMER) {
|
||||
/* limit convert_arg to keep scan_begin_arg in range */
|
||||
limit = UINT_MAX / cmd->scan_end_arg;
|
||||
limit = rounddown(limit, (unsigned int)NSEC_PER_SEC);
|
||||
limit = rounddown(limit, (unsigned int)NSEC_PER_USEC);
|
||||
arg = min(arg, limit);
|
||||
}
|
||||
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
|
||||
|
||||
@@ -124,7 +124,8 @@ struct counter_device *counter_alloc(size_t sizeof_priv)
|
||||
|
||||
err_dev_set_name:
|
||||
|
||||
counter_chrdev_remove(counter);
|
||||
put_device(dev);
|
||||
return NULL;
|
||||
err_chrdev_add:
|
||||
|
||||
ida_free(&counter_ida, dev->id);
|
||||
|
||||
@@ -876,14 +876,14 @@ static int ad4695_offload_buffer_postenable(struct iio_dev *indio_dev)
|
||||
if (ret)
|
||||
goto err_unoptimize_message;
|
||||
|
||||
ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
|
||||
&config);
|
||||
ret = ad4695_enter_advanced_sequencer_mode(st, num_slots);
|
||||
if (ret)
|
||||
goto err_disable_busy_output;
|
||||
|
||||
ret = ad4695_enter_advanced_sequencer_mode(st, num_slots);
|
||||
ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
|
||||
&config);
|
||||
if (ret)
|
||||
goto err_offload_trigger_disable;
|
||||
goto err_exit_conversion_mode;
|
||||
|
||||
mutex_lock(&st->cnv_pwm_lock);
|
||||
pwm_get_state(st->cnv_pwm, &state);
|
||||
@@ -895,23 +895,16 @@ static int ad4695_offload_buffer_postenable(struct iio_dev *indio_dev)
|
||||
ret = pwm_apply_might_sleep(st->cnv_pwm, &state);
|
||||
mutex_unlock(&st->cnv_pwm_lock);
|
||||
if (ret)
|
||||
goto err_offload_exit_conversion_mode;
|
||||
goto err_offload_trigger_disable;
|
||||
|
||||
return 0;
|
||||
|
||||
err_offload_exit_conversion_mode:
|
||||
/*
|
||||
* We have to unwind in a different order to avoid triggering offload.
|
||||
* ad4695_exit_conversion_mode() triggers a conversion, so it has to be
|
||||
* done after spi_offload_trigger_disable().
|
||||
*/
|
||||
spi_offload_trigger_disable(st->offload, st->offload_trigger);
|
||||
ad4695_exit_conversion_mode(st);
|
||||
goto err_disable_busy_output;
|
||||
|
||||
err_offload_trigger_disable:
|
||||
spi_offload_trigger_disable(st->offload, st->offload_trigger);
|
||||
|
||||
err_exit_conversion_mode:
|
||||
ad4695_exit_conversion_mode(st);
|
||||
|
||||
err_disable_busy_output:
|
||||
regmap_clear_bits(st->regmap, AD4695_REG_GP_MODE,
|
||||
AD4695_REG_GP_MODE_BUSY_GP_EN);
|
||||
|
||||
@@ -817,9 +817,11 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
|
||||
}
|
||||
|
||||
priv->tsc_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "amlogic,hhi-sysctrl");
|
||||
if (IS_ERR(priv->tsc_regmap))
|
||||
if (IS_ERR(priv->tsc_regmap)) {
|
||||
kfree(buf);
|
||||
return dev_err_probe(dev, PTR_ERR(priv->tsc_regmap),
|
||||
"failed to get amlogic,hhi-sysctrl regmap\n");
|
||||
}
|
||||
|
||||
trimming_bits = priv->param->temperature_trimming_bits;
|
||||
trimming_mask = BIT(trimming_bits) - 1;
|
||||
|
||||
@@ -497,6 +497,7 @@ static int mt6358_read_imp(struct mt6359_auxadc *adc_dev,
|
||||
return ret;
|
||||
|
||||
/* Read the params before stopping */
|
||||
val_v = 0;
|
||||
regmap_read(regmap, reg_adc0 + (cinfo->imp_adc_num << 1), &val_v);
|
||||
|
||||
mt6358_stop_imp_conv(adc_dev);
|
||||
|
||||
@@ -231,7 +231,7 @@ static int npcm_adc_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(info->reset))
|
||||
return PTR_ERR(info->reset);
|
||||
|
||||
info->adc_clk = devm_clk_get(&pdev->dev, NULL);
|
||||
info->adc_clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(info->adc_clk)) {
|
||||
dev_warn(&pdev->dev, "ADC clock failed: can't read clk\n");
|
||||
return PTR_ERR(info->adc_clk);
|
||||
@@ -244,17 +244,13 @@ static int npcm_adc_probe(struct platform_device *pdev)
|
||||
info->adc_sample_hz = clk_get_rate(info->adc_clk) / ((div + 1) * 2);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto err_disable_clk;
|
||||
}
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, npcm_adc_isr, 0,
|
||||
"NPCM_ADC", indio_dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed requesting interrupt\n");
|
||||
goto err_disable_clk;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
reg_con = ioread32(info->regs + NPCM_ADCCON);
|
||||
info->vref = devm_regulator_get_optional(&pdev->dev, "vref");
|
||||
@@ -262,7 +258,7 @@ static int npcm_adc_probe(struct platform_device *pdev)
|
||||
ret = regulator_enable(info->vref);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Can't enable ADC reference voltage\n");
|
||||
goto err_disable_clk;
|
||||
return ret;
|
||||
}
|
||||
|
||||
iowrite32(reg_con & ~NPCM_ADCCON_REFSEL,
|
||||
@@ -272,10 +268,8 @@ static int npcm_adc_probe(struct platform_device *pdev)
|
||||
* Any error which is not ENODEV indicates the regulator
|
||||
* has been specified and so is a failure case.
|
||||
*/
|
||||
if (PTR_ERR(info->vref) != -ENODEV) {
|
||||
ret = PTR_ERR(info->vref);
|
||||
goto err_disable_clk;
|
||||
}
|
||||
if (PTR_ERR(info->vref) != -ENODEV)
|
||||
return PTR_ERR(info->vref);
|
||||
|
||||
/* Use internal reference */
|
||||
iowrite32(reg_con | NPCM_ADCCON_REFSEL,
|
||||
@@ -314,8 +308,6 @@ err_iio_register:
|
||||
iowrite32(reg_con & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
|
||||
if (!IS_ERR(info->vref))
|
||||
regulator_disable(info->vref);
|
||||
err_disable_clk:
|
||||
clk_disable_unprepare(info->adc_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -332,7 +324,6 @@ static void npcm_adc_remove(struct platform_device *pdev)
|
||||
iowrite32(regtemp & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
|
||||
if (!IS_ERR(info->vref))
|
||||
regulator_disable(info->vref);
|
||||
clk_disable_unprepare(info->adc_clk);
|
||||
}
|
||||
|
||||
static struct platform_driver npcm_adc_driver = {
|
||||
|
||||
@@ -198,6 +198,15 @@ static void nxp_sar_adc_irq_cfg(struct nxp_sar_adc *info, bool enable)
|
||||
writel(0, NXP_SAR_ADC_IMR(info->regs));
|
||||
}
|
||||
|
||||
static void nxp_sar_adc_wait_for(struct nxp_sar_adc *info, unsigned int cycles)
|
||||
{
|
||||
u64 rate;
|
||||
|
||||
rate = clk_get_rate(info->clk);
|
||||
if (rate)
|
||||
ndelay(div64_u64(NSEC_PER_SEC, rate * cycles));
|
||||
}
|
||||
|
||||
static bool nxp_sar_adc_set_enabled(struct nxp_sar_adc *info, bool enable)
|
||||
{
|
||||
u32 mcr;
|
||||
@@ -221,7 +230,7 @@ static bool nxp_sar_adc_set_enabled(struct nxp_sar_adc *info, bool enable)
|
||||
* configuration of NCMR and the setting of NSTART.
|
||||
*/
|
||||
if (enable)
|
||||
ndelay(div64_u64(NSEC_PER_SEC, clk_get_rate(info->clk) * 3));
|
||||
nxp_sar_adc_wait_for(info, 3);
|
||||
|
||||
return pwdn;
|
||||
}
|
||||
@@ -469,7 +478,7 @@ static void nxp_sar_adc_stop_conversion(struct nxp_sar_adc *info)
|
||||
* only when the capture finishes. The delay will be very
|
||||
* short, usec-ish, which is acceptable in the atomic context.
|
||||
*/
|
||||
ndelay(div64_u64(NSEC_PER_SEC, clk_get_rate(info->clk)) * 80);
|
||||
nxp_sar_adc_wait_for(info, 80);
|
||||
}
|
||||
|
||||
static int nxp_sar_adc_start_conversion(struct nxp_sar_adc *info, bool raw)
|
||||
@@ -560,6 +569,9 @@ static int nxp_sar_adc_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
if (val <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Configures the sample period duration in terms of the SAR
|
||||
* controller clock. The minimum acceptable value is 8.
|
||||
@@ -568,7 +580,11 @@ static int nxp_sar_adc_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec
|
||||
* sampling timing which gives us the number of cycles expected.
|
||||
* The value is 8-bit wide, consequently the max value is 0xFF.
|
||||
*/
|
||||
inpsamp = clk_get_rate(info->clk) / val - NXP_SAR_ADC_CONV_TIME;
|
||||
inpsamp = clk_get_rate(info->clk) / val;
|
||||
if (inpsamp < NXP_SAR_ADC_CONV_TIME)
|
||||
return -EINVAL;
|
||||
|
||||
inpsamp -= NXP_SAR_ADC_CONV_TIME;
|
||||
nxp_sar_adc_conversion_timing_set(info, inpsamp);
|
||||
return 0;
|
||||
|
||||
@@ -660,7 +676,7 @@ static void nxp_sar_adc_dma_cb(void *data)
|
||||
static int nxp_sar_adc_start_cyclic_dma(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct nxp_sar_adc *info = iio_priv(indio_dev);
|
||||
struct dma_slave_config config;
|
||||
struct dma_slave_config config = { };
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -482,7 +482,7 @@ static int adc5_gen3_get_fw_channel_data(struct adc5_chip *adc,
|
||||
sid = FIELD_GET(ADC5_GEN3_VIRTUAL_SID_MASK, chan);
|
||||
chan = FIELD_GET(ADC5_GEN3_CHANNEL_MASK, chan);
|
||||
|
||||
if (chan > ADC5_MAX_CHANNEL)
|
||||
if (chan >= ADC5_MAX_CHANNEL)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"%s invalid channel number %d\n",
|
||||
name, chan);
|
||||
|
||||
@@ -70,8 +70,10 @@ static int vprbrd_iio_read_raw(struct iio_dev *iio_dev,
|
||||
VPRBRD_USB_TYPE_OUT, 0x0000, 0x0000, admsg,
|
||||
sizeof(struct vprbrd_adc_msg), VPRBRD_USB_TIMEOUT_MS);
|
||||
if (ret != sizeof(struct vprbrd_adc_msg)) {
|
||||
dev_err(&iio_dev->dev, "usb send error on adc read\n");
|
||||
mutex_unlock(&vb->lock);
|
||||
error = -EREMOTEIO;
|
||||
dev_err(&iio_dev->dev, "usb send error on adc read\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = usb_control_msg(vb->usb_dev,
|
||||
|
||||
@@ -817,6 +817,7 @@ static int xadc_postdisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct xadc *xadc = iio_priv(indio_dev);
|
||||
unsigned long scan_mask;
|
||||
int seq_mode;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
@@ -824,6 +825,12 @@ static int xadc_postdisable(struct iio_dev *indio_dev)
|
||||
for (i = 0; i < indio_dev->num_channels; i++)
|
||||
scan_mask |= BIT(indio_dev->channels[i].scan_index);
|
||||
|
||||
/*
|
||||
* Use the correct sequencer mode for the idle state: simultaneous
|
||||
* mode for dual external mux configurations, continuous otherwise.
|
||||
*/
|
||||
seq_mode = xadc_get_seq_mode(xadc, scan_mask);
|
||||
|
||||
/* Enable all channels and calibration */
|
||||
ret = xadc_write_adc_reg(xadc, XADC_REG_SEQ(0), scan_mask & 0xffff);
|
||||
if (ret)
|
||||
@@ -834,11 +841,11 @@ static int xadc_postdisable(struct iio_dev *indio_dev)
|
||||
return ret;
|
||||
|
||||
ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_SEQ_MASK,
|
||||
XADC_CONF1_SEQ_CONTINUOUS);
|
||||
seq_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return xadc_power_adc_b(xadc, XADC_CONF1_SEQ_CONTINUOUS);
|
||||
return xadc_power_adc_b(xadc, seq_mode);
|
||||
}
|
||||
|
||||
static int xadc_preenable(struct iio_dev *indio_dev)
|
||||
|
||||
@@ -85,7 +85,7 @@ static struct hw_consumer_buffer *iio_hw_consumer_get_buffer(
|
||||
*/
|
||||
struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev)
|
||||
{
|
||||
struct hw_consumer_buffer *buf;
|
||||
struct hw_consumer_buffer *buf, *tmp;
|
||||
struct iio_hw_consumer *hwc;
|
||||
struct iio_channel *chan;
|
||||
int ret;
|
||||
@@ -116,7 +116,7 @@ struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev)
|
||||
return hwc;
|
||||
|
||||
err_put_buffers:
|
||||
list_for_each_entry(buf, &hwc->buffers, head)
|
||||
list_for_each_entry_safe(buf, tmp, &hwc->buffers, head)
|
||||
iio_buffer_put(&buf->buffer);
|
||||
iio_channel_release_all(hwc->channels);
|
||||
err_free_hwc:
|
||||
|
||||
@@ -52,6 +52,8 @@ struct mhz19b_state {
|
||||
struct completion buf_ready;
|
||||
|
||||
u8 buf_idx;
|
||||
bool buf_overflow;
|
||||
|
||||
/*
|
||||
* Serdev receive buffer.
|
||||
* When data is received from the MH-Z19B,
|
||||
@@ -106,6 +108,10 @@ static int mhz19b_serdev_cmd(struct iio_dev *indio_dev, int cmd, u16 arg)
|
||||
cmd_buf[8] = mhz19b_get_checksum(cmd_buf);
|
||||
|
||||
/* Write buf to uart ctrl synchronously */
|
||||
st->buf_idx = 0;
|
||||
st->buf_overflow = false;
|
||||
reinit_completion(&st->buf_ready);
|
||||
|
||||
ret = serdev_device_write(serdev, cmd_buf, MHZ19B_CMD_SIZE, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -121,6 +127,9 @@ static int mhz19b_serdev_cmd(struct iio_dev *indio_dev, int cmd, u16 arg)
|
||||
if (!ret)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (st->buf_overflow)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (st->buf[8] != mhz19b_get_checksum(st->buf)) {
|
||||
dev_err(dev, "checksum err");
|
||||
return -EINVAL;
|
||||
@@ -240,6 +249,14 @@ static size_t mhz19b_receive_buf(struct serdev_device *serdev,
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev);
|
||||
struct mhz19b_state *st = iio_priv(indio_dev);
|
||||
size_t remaining = MHZ19B_CMD_SIZE - st->buf_idx;
|
||||
|
||||
if (len > remaining) {
|
||||
st->buf_idx = 0;
|
||||
st->buf_overflow = true;
|
||||
complete(&st->buf_ready);
|
||||
return len;
|
||||
}
|
||||
|
||||
memcpy(st->buf + st->buf_idx, data, len);
|
||||
st->buf_idx += len;
|
||||
|
||||
@@ -256,7 +256,7 @@ static int scd30_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const
|
||||
guard(mutex)(&state->lock);
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
if (val)
|
||||
if (val || !val2)
|
||||
return -EINVAL;
|
||||
|
||||
val = 1000000000 / val2;
|
||||
|
||||
@@ -590,6 +590,7 @@ static void ssp_remove(struct spi_device *spi)
|
||||
ssp_clean_pending_list(data);
|
||||
|
||||
free_irq(data->spi->irq, data);
|
||||
cancel_delayed_work_sync(&data->work_refresh);
|
||||
|
||||
timer_delete_sync(&data->wdt_timer);
|
||||
cancel_work_sync(&data->work_wdt);
|
||||
|
||||
+40
-14
@@ -105,6 +105,12 @@ static const char * const ad3530r_powerdown_modes[] = {
|
||||
"32kohm_to_gnd",
|
||||
};
|
||||
|
||||
static const char * const ad3531r_powerdown_modes[] = {
|
||||
"500ohm_to_gnd",
|
||||
"3.85kohm_to_gnd",
|
||||
"16kohm_to_gnd",
|
||||
};
|
||||
|
||||
static int ad3530r_get_powerdown_mode(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan)
|
||||
{
|
||||
@@ -133,6 +139,13 @@ static const struct iio_enum ad3530r_powerdown_mode_enum = {
|
||||
.set = ad3530r_set_powerdown_mode,
|
||||
};
|
||||
|
||||
static const struct iio_enum ad3531r_powerdown_mode_enum = {
|
||||
.items = ad3531r_powerdown_modes,
|
||||
.num_items = ARRAY_SIZE(ad3531r_powerdown_modes),
|
||||
.get = ad3530r_get_powerdown_mode,
|
||||
.set = ad3530r_set_powerdown_mode,
|
||||
};
|
||||
|
||||
static ssize_t ad3530r_get_dac_powerdown(struct iio_dev *indio_dev,
|
||||
uintptr_t private,
|
||||
const struct iio_chan_spec *chan,
|
||||
@@ -276,7 +289,20 @@ static const struct iio_chan_spec_ext_info ad3530r_ext_info[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
#define AD3530R_CHAN(_chan) \
|
||||
static const struct iio_chan_spec_ext_info ad3531r_ext_info[] = {
|
||||
{
|
||||
.name = "powerdown",
|
||||
.shared = IIO_SEPARATE,
|
||||
.read = ad3530r_get_dac_powerdown,
|
||||
.write = ad3530r_set_dac_powerdown,
|
||||
},
|
||||
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad3531r_powerdown_mode_enum),
|
||||
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
|
||||
&ad3531r_powerdown_mode_enum),
|
||||
{ }
|
||||
};
|
||||
|
||||
#define AD3530R_CHAN(_chan, _ext_info) \
|
||||
{ \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
@@ -284,25 +310,25 @@ static const struct iio_chan_spec_ext_info ad3530r_ext_info[] = {
|
||||
.output = 1, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.ext_info = ad3530r_ext_info, \
|
||||
.ext_info = _ext_info, \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec ad3530r_channels[] = {
|
||||
AD3530R_CHAN(0),
|
||||
AD3530R_CHAN(1),
|
||||
AD3530R_CHAN(2),
|
||||
AD3530R_CHAN(3),
|
||||
AD3530R_CHAN(4),
|
||||
AD3530R_CHAN(5),
|
||||
AD3530R_CHAN(6),
|
||||
AD3530R_CHAN(7),
|
||||
AD3530R_CHAN(0, ad3530r_ext_info),
|
||||
AD3530R_CHAN(1, ad3530r_ext_info),
|
||||
AD3530R_CHAN(2, ad3530r_ext_info),
|
||||
AD3530R_CHAN(3, ad3530r_ext_info),
|
||||
AD3530R_CHAN(4, ad3530r_ext_info),
|
||||
AD3530R_CHAN(5, ad3530r_ext_info),
|
||||
AD3530R_CHAN(6, ad3530r_ext_info),
|
||||
AD3530R_CHAN(7, ad3530r_ext_info),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad3531r_channels[] = {
|
||||
AD3530R_CHAN(0),
|
||||
AD3530R_CHAN(1),
|
||||
AD3530R_CHAN(2),
|
||||
AD3530R_CHAN(3),
|
||||
AD3530R_CHAN(0, ad3531r_ext_info),
|
||||
AD3530R_CHAN(1, ad3531r_ext_info),
|
||||
AD3530R_CHAN(2, ad3531r_ext_info),
|
||||
AD3530R_CHAN(3, ad3531r_ext_info),
|
||||
};
|
||||
|
||||
static const struct ad3530r_chip_info ad3530_chip = {
|
||||
|
||||
+42
-14
@@ -25,22 +25,37 @@ static const char * const ad5686_powerdown_modes[] = {
|
||||
"three_state"
|
||||
};
|
||||
|
||||
static inline unsigned int ad5686_pd_mask_shift(const struct iio_chan_spec *chan)
|
||||
{
|
||||
if (chan->channel == chan->address)
|
||||
return chan->channel * 2;
|
||||
|
||||
/* one-hot encoding is used in dual/quad channel devices */
|
||||
return __ffs(chan->address) * 2;
|
||||
}
|
||||
|
||||
static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan)
|
||||
{
|
||||
unsigned int shift = ad5686_pd_mask_shift(chan);
|
||||
struct ad5686_state *st = iio_priv(indio_dev);
|
||||
|
||||
return ((st->pwr_down_mode >> (chan->channel * 2)) & 0x3) - 1;
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
return ((st->pwr_down_mode >> shift) & 0x3U) - 1;
|
||||
}
|
||||
|
||||
static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
unsigned int mode)
|
||||
{
|
||||
unsigned int shift = ad5686_pd_mask_shift(chan);
|
||||
struct ad5686_state *st = iio_priv(indio_dev);
|
||||
|
||||
st->pwr_down_mode &= ~(0x3 << (chan->channel * 2));
|
||||
st->pwr_down_mode |= ((mode + 1) << (chan->channel * 2));
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
st->pwr_down_mode &= ~(0x3U << shift);
|
||||
st->pwr_down_mode |= (mode + 1) << shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -55,10 +70,12 @@ static const struct iio_enum ad5686_powerdown_mode_enum = {
|
||||
static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev,
|
||||
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
|
||||
{
|
||||
unsigned int shift = ad5686_pd_mask_shift(chan);
|
||||
struct ad5686_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sysfs_emit(buf, "%d\n", !!(st->pwr_down_mask &
|
||||
(0x3 << (chan->channel * 2))));
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
return sysfs_emit(buf, "%d\n", !!(st->pwr_down_mask & (0x3U << shift)));
|
||||
}
|
||||
|
||||
static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
@@ -77,10 +94,12 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
if (readin)
|
||||
st->pwr_down_mask |= (0x3 << (chan->channel * 2));
|
||||
st->pwr_down_mask |= 0x3U << ad5686_pd_mask_shift(chan);
|
||||
else
|
||||
st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
|
||||
st->pwr_down_mask &= ~(0x3U << ad5686_pd_mask_shift(chan));
|
||||
|
||||
switch (st->chip_info->regmap_type) {
|
||||
case AD5310_REGMAP:
|
||||
@@ -154,7 +173,7 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
if (val > (1 << chan->scan_type.realbits) || val < 0)
|
||||
if (val >= (1 << chan->scan_type.realbits) || val < 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
@@ -460,7 +479,7 @@ int ad5686_probe(struct device *dev,
|
||||
{
|
||||
struct ad5686_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
unsigned int val, ref_bit_msk;
|
||||
unsigned int val, ref_bit_msk, shift;
|
||||
bool has_external_vref;
|
||||
u8 cmd;
|
||||
int ret, i;
|
||||
@@ -484,9 +503,18 @@ int ad5686_probe(struct device *dev,
|
||||
has_external_vref = ret != -ENODEV;
|
||||
st->vref_mv = has_external_vref ? ret / 1000 : st->chip_info->int_vref_mv;
|
||||
|
||||
/* Initialize masks to all ones provided the max shift (last channel) */
|
||||
shift = ad5686_pd_mask_shift(&st->chip_info->channels[st->chip_info->num_channels - 1]);
|
||||
st->pwr_down_mask = GENMASK(shift + 1, 0);
|
||||
st->pwr_down_mode = GENMASK(shift + 1, 0);
|
||||
|
||||
/* Set all the power down mode for all channels to 1K pulldown */
|
||||
for (i = 0; i < st->chip_info->num_channels; i++)
|
||||
st->pwr_down_mode |= (0x01 << (i * 2));
|
||||
for (i = 0; i < st->chip_info->num_channels; i++) {
|
||||
shift = ad5686_pd_mask_shift(&st->chip_info->channels[i]);
|
||||
st->pwr_down_mask &= ~(0x3U << shift); /* powered up state */
|
||||
st->pwr_down_mode &= ~(0x3U << shift);
|
||||
st->pwr_down_mode |= 0x01U << shift;
|
||||
}
|
||||
|
||||
indio_dev->name = name;
|
||||
indio_dev->info = &ad5686_info;
|
||||
@@ -509,7 +537,7 @@ int ad5686_probe(struct device *dev,
|
||||
break;
|
||||
case AD5686_REGMAP:
|
||||
cmd = AD5686_CMD_INTERNAL_REFER_SETUP;
|
||||
ref_bit_msk = 0;
|
||||
ref_bit_msk = AD5686_REF_BIT_MSK;
|
||||
break;
|
||||
case AD5693_REGMAP:
|
||||
cmd = AD5686_CMD_CONTROL_REG;
|
||||
@@ -520,9 +548,9 @@ int ad5686_probe(struct device *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = (has_external_vref | ref_bit_msk);
|
||||
val = has_external_vref ? ref_bit_msk : 0;
|
||||
|
||||
ret = st->write(st, cmd, 0, !!val);
|
||||
ret = st->write(st, cmd, 0, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
#define AD5310_REF_BIT_MSK BIT(8)
|
||||
#define AD5683_REF_BIT_MSK BIT(12)
|
||||
#define AD5686_REF_BIT_MSK BIT(0)
|
||||
#define AD5693_REF_BIT_MSK BIT(12)
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user