From 6456487cc0a770a4ccdb33d8e9cfc984e337294c Mon Sep 17 00:00:00 2001 From: Lei Qian Date: Thu, 17 Oct 2019 14:35:41 +0800 Subject: [PATCH] meson_saradc: merge from mainline PD#SWPL-15312 Change-Id: I77692c66e245135f8f325702626c52c24eb3e180 Signed-off-by: Lei Qian --- drivers/amlogic/iio/adc/meson_saradc.c | 61 ++++++++++++++++++++------ 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/drivers/amlogic/iio/adc/meson_saradc.c b/drivers/amlogic/iio/adc/meson_saradc.c index 8365c4ef39e8..16dbb6946b94 100644 --- a/drivers/amlogic/iio/adc/meson_saradc.c +++ b/drivers/amlogic/iio/adc/meson_saradc.c @@ -214,9 +214,7 @@ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \ BIT(IIO_CHAN_INFO_PROCESSED), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_CALIBBIAS) | \ - BIT(IIO_CHAN_INFO_CALIBSCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .scan_type = { \ .sign = 'u', \ .storagebits = 16, \ @@ -326,6 +324,7 @@ struct meson_sar_adc_reg_diff { * @obt_temp_chan6: whether to read data of temp sensor by channel 6 * @has_bl30_integration: * @vref_sel: txlx and later: VDDA; others(txl etc): calibration voltage + * @calib_enable: txlx and later: disable; others(txl etc): enable * @period_support: periodic sampling support * @has_chnl_regs: whether support for chnl[X] registers * @resolution: gxl and later: 12bit; others(gxtvbb etc): 10bit @@ -336,6 +335,7 @@ struct meson_sar_adc_data { bool obt_temp_chan6; bool has_bl30_integration; bool vref_sel; + bool calib_enable; bool period_support; bool has_chnl_regs; unsigned int resolution; @@ -455,7 +455,10 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, fifo_val &= GENMASK(priv->data->resolution - 1, 0); /* to fix the sample value by software */ - *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + if (priv->data->calib_enable) + *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + else + *val = fifo_val; return 0; } @@ -496,7 +499,10 @@ static int meson_sar_adc_read_raw_sample_from_chnl(struct iio_dev *indio_dev, fifo_val &= GENMASK(priv->data->resolution - 1, 0); /* to fix the sample value by software */ - *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + if (priv->data->calib_enable) + *val = meson_sar_adc_calib_val(indio_dev, fifo_val); + else + *val = fifo_val; return 0; } @@ -614,6 +620,7 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) mutex_lock(&indio_dev->mlock); if (priv->data->has_bl30_integration) { +again: /* wait until BL30 releases it's lock (so we can use * the SAR ADC) */ @@ -631,10 +638,10 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) MESON_SAR_ADC_DELAY_KERNEL_BUSY); isb(); dsb(sy); - udelay(1); + udelay(5); regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); if (val & MESON_SAR_ADC_DELAY_BL30_BUSY) - return -ETIMEDOUT; + goto again; } return 0; @@ -644,10 +651,14 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - if (priv->data->has_bl30_integration) + if (priv->data->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); + isb(); + dsb(sy); + udelay(5); + } mutex_unlock(&indio_dev->mlock); } @@ -762,10 +773,16 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_CALIBBIAS: + if (!priv->data->calib_enable) + return -EINVAL; + *val = priv->calibbias; return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBSCALE: + if (!priv->data->calib_enable) + return -EINVAL; + *val = priv->calibscale / MILLION; *val2 = priv->calibscale % MILLION; return IIO_VAL_INT_PLUS_MICRO; @@ -1433,6 +1450,7 @@ struct meson_sar_adc_data meson_sar_adc_txl_data = { .obt_temp_chan6 = false, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_12BIT, .name = "meson-txl-saradc", .regmap_config = &meson_sar_adc_regmap_config_gxbb, @@ -1448,6 +1466,7 @@ struct meson_sar_adc_data meson_sar_adc_gxl_data = { .obt_temp_chan6 = false, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_12BIT, .name = "meson-gxl-saradc", .regmap_config = &meson_sar_adc_regmap_config_gxbb, @@ -1463,6 +1482,7 @@ struct meson_sar_adc_data meson_sar_adc_gxm_data = { .obt_temp_chan6 = false, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_12BIT, .name = "meson-gxm-saradc", .regmap_config = &meson_sar_adc_regmap_config_gxbb, @@ -1478,6 +1498,7 @@ struct meson_sar_adc_data meson_sar_adc_m8b_data = { .obt_temp_chan6 = true, .has_bl30_integration = true, .vref_sel = CALIB_VOL_AS_VREF, + .calib_enable = true, .resolution = SAR_ADC_10BIT, .name = "meson-m8b-saradc", .regmap_config = &meson_sar_adc_regmap_config_meson8, @@ -1520,8 +1541,10 @@ static int meson_sar_adc_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; const struct of_device_id *match; + struct iio_chan_spec *chan; int ret; int irq; + int i; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); if (!indio_dev) { @@ -1593,8 +1616,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return ret; } - priv->calibscale = MILLION; - if (priv->data->period_support) { ret = of_property_read_u32(pdev->dev.of_node, "amlogic,delay-per-tick", &priv->delay_per_tick); @@ -1633,10 +1654,24 @@ static int meson_sar_adc_probe(struct platform_device *pdev) if (ret) goto err; - ret = meson_sar_adc_calib(indio_dev); - if (ret) - dev_warn(&pdev->dev, "calibration failed\n"); + if (priv->data->calib_enable) { + priv->calibscale = MILLION; + for (i = 0; i < indio_dev->num_channels; i++) { + chan = (struct iio_chan_spec *)indio_dev->channels + i; + if (chan->channel < 0) + continue; + + chan->info_mask_shared_by_all = + BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_CALIBSCALE); + + } + ret = meson_sar_adc_calib(indio_dev); + if (ret) + dev_warn(&pdev->dev, "calibration failed\n"); + + } platform_set_drvdata(pdev, indio_dev); ret = iio_device_register(indio_dev);