[PATCH v2 08/11] iio: adc: sun4i-gpadc-iio: add support for A33 thermal sensor

Jonathan Cameron jic23 at kernel.org
Sat Mar 18 07:18:02 PDT 2017


On 14/03/17 07:15, Quentin Schulz wrote:
> Hi Jonathan,
> 
> On 14/03/2017 06:18, Icenowy Zheng wrote:
>>
>>
>> 14.03.2017, 05:08, "Jonathan Cameron" <jic23 at kernel.org>:
>>> On 10/03/17 10:39, Quentin Schulz wrote:
>>>>  This adds support for the Allwinner A33 thermal sensor.
>>>>
>>>>  Unlike the A10, A13 and A31, the Allwinner A33 only has one channel
>>>>  which is dedicated to the thermal sensor. Moreover, its thermal sensor
>>>>  does not generate interruptions, thus we only need to directly read the
>>>>  register storing the temperature value.
>>>>
>>>>  The MFD used by the A10, A13 and A31, was created to avoid breaking the
>>>>  DT binding, but since the nodes for the ADC weren't there for the A33,
>>>>  it is not needed.
>>>>
>>>>  Signed-off-by: Quentin Schulz <quentin.schulz at free-electrons.com>
>>>
>>> Talk me through why it makes sense to do this rather than simply spin out
>>> a really simple thermal driver for the A33?
>>
>> According to him the A33 thermal sensor is a simplified version of the GPADC.
>>
> 
> Same registers with almost same bits for the same purpose (temperature).
> Some SoCs have an ADC and one or more thermal sensors (A10, A13, A31,
> H3) while others have only one thermal sensor (A23, A33). Same IP with
> or without ADC/Touchscreen so same driver, that was my mindset.
> 
> The thermal part behaves the same except for the presence of interrupts
> or not. (A33 has bits for interrupts in the datasheet but that just does
> not work).
Hmm. I'm just about convinced by this argument, please make it in the patch
description going forward.

Jonathan
> 
> Thanks,
> Quentin
> 
>> I have already did a simple thermal driver ~8 months ago, but is rejected for
>> this reason.
>>
>>>
>>> I'm not against what you have here, but don't feel it has been fully argued.
>>>
>>> Jonathan
>>>>  ---
>>>>
>>>>  v2:
>>>>    - removed added comments in Kconfig,
>>>>    - simplified Kconfig depends on condition,
>>>>    - removed THERMAL_OF requirement for sun8i,
>>>>    - renamed sun8i_gpadc_channels to sun8i_a33_gpadc_channels,
>>>>    - renamed use_dt boolean in no_irq as it reflects better why we need it,
>>>>    - removed spurious/unneeded modifications done in v1,
>>>>
>>>>   drivers/iio/adc/Kconfig | 2 +-
>>>>   drivers/iio/adc/sun4i-gpadc-iio.c | 100 ++++++++++++++++++++++++++++++++++++--
>>>>   include/linux/mfd/sun4i-gpadc.h | 4 ++
>>>>   3 files changed, 102 insertions(+), 4 deletions(-)
>>>>
>>>>  diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>>>>  index 9f8b4b1..8c8ead6 100644
>>>>  --- a/drivers/iio/adc/Kconfig
>>>>  +++ b/drivers/iio/adc/Kconfig
>>>>  @@ -562,7 +562,7 @@ config STX104
>>>>   config SUN4I_GPADC
>>>>           tristate "Support for the Allwinner SoCs GPADC"
>>>>           depends on IIO
>>>>  - depends on MFD_SUN4I_GPADC
>>>>  + depends on MFD_SUN4I_GPADC || MACH_SUN8I
>>>>           help
>>>>             Say yes here to build support for Allwinner (A10, A13 and A31) SoCs
>>>>             GPADC. This ADC provides 4 channels which can be used as an ADC or as
>>>>  diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
>>>>  index 7cb997a..70684cd 100644
>>>>  --- a/drivers/iio/adc/sun4i-gpadc-iio.c
>>>>  +++ b/drivers/iio/adc/sun4i-gpadc-iio.c
>>>>  @@ -85,6 +85,12 @@ static const struct gpadc_data sun6i_gpadc_data = {
>>>>           .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK,
>>>>   };
>>>>
>>>>  +static const struct gpadc_data sun8i_a33_gpadc_data = {
>>>>  + .temp_offset = -1662,
>>>>  + .temp_scale = 162,
>>>>  + .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN,
>>>>  +};
>>>>  +
>>>>   struct sun4i_gpadc_iio {
>>>>           struct iio_dev *indio_dev;
>>>>           struct completion completion;
>>>>  @@ -96,6 +102,7 @@ struct sun4i_gpadc_iio {
>>>>           unsigned int temp_data_irq;
>>>>           atomic_t ignore_temp_data_irq;
>>>>           const struct gpadc_data *data;
>>>>  + bool no_irq;
>>>>           /* prevents concurrent reads of temperature and ADC */
>>>>           struct mutex mutex;
>>>>   };
>>>>  @@ -138,6 +145,23 @@ static const struct iio_chan_spec sun4i_gpadc_channels_no_temp[] = {
>>>>           SUN4I_GPADC_ADC_CHANNEL(3, "adc_chan3"),
>>>>   };
>>>>
>>>>  +static const struct iio_chan_spec sun8i_a33_gpadc_channels[] = {
>>>>  + {
>>>>  + .type = IIO_TEMP,
>>>>  + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
>>>>  + BIT(IIO_CHAN_INFO_SCALE) |
>>>>  + BIT(IIO_CHAN_INFO_OFFSET),
>>>>  + .datasheet_name = "temp_adc",
>>>>  + },
>>>>  +};
>>>>  +
>>>>  +static const struct regmap_config sun4i_gpadc_regmap_config = {
>>>>  + .reg_bits = 32,
>>>>  + .val_bits = 32,
>>>>  + .reg_stride = 4,
>>>>  + .fast_io = true,
>>>>  +};
>>>>  +
>>>>   static int sun4i_prepare_for_irq(struct iio_dev *indio_dev, int channel,
>>>>                                    unsigned int irq)
>>>>   {
>>>>  @@ -247,6 +271,17 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val)
>>>>   {
>>>>           struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
>>>>
>>>>  + if (info->no_irq) {
>>>>  + pm_runtime_get_sync(indio_dev->dev.parent);
>>>>  +
>>>>  + regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val);
>>>>  +
>>>>  + pm_runtime_mark_last_busy(indio_dev->dev.parent);
>>>>  + pm_runtime_put_autosuspend(indio_dev->dev.parent);
>>>>  +
>>>>  + return 0;
>>>>  + }
>>>>  +
>>>>           return sun4i_gpadc_read(indio_dev, 0, val, info->temp_data_irq);
>>>>   }
>>>>
>>>>  @@ -454,6 +489,58 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name,
>>>>           return 0;
>>>>   }
>>>>
>>>>  +static const struct of_device_id sun4i_gpadc_of_id[] = {
>>>>  + {
>>>>  + .compatible = "allwinner,sun8i-a33-gpadc-iio",
>>>>  + .data = &sun8i_a33_gpadc_data,
>>>>  + },
>>>>  + { /* sentinel */ }
>>>>  +};
>>>>  +
>>>>  +static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
>>>>  + struct iio_dev *indio_dev)
>>>>  +{
>>>>  + struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
>>>>  + const struct of_device_id *of_dev;
>>>>  + struct thermal_zone_device *tzd;
>>>>  + struct resource *mem;
>>>>  + void __iomem *base;
>>>>  + int ret;
>>>>  +
>>>>  + of_dev = of_match_device(sun4i_gpadc_of_id, &pdev->dev);
>>>>  + if (!of_dev)
>>>>  + return -ENODEV;
>>>>  +
>>>>  + info->no_irq = true;
>>>>  + info->data = (struct gpadc_data *)of_dev->data;
>>>>  + indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels);
>>>>  + indio_dev->channels = sun8i_a33_gpadc_channels;
>>>>  +
>>>>  + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>  + base = devm_ioremap_resource(&pdev->dev, mem);
>>>>  + if (IS_ERR(base))
>>>>  + return PTR_ERR(base);
>>>>  +
>>>>  + info->regmap = devm_regmap_init_mmio(&pdev->dev, base,
>>>>  + &sun4i_gpadc_regmap_config);
>>>>  + if (IS_ERR(info->regmap)) {
>>>>  + ret = PTR_ERR(info->regmap);
>>>>  + dev_err(&pdev->dev, "failed to init regmap: %d\n", ret);
>>>>  + return ret;
>>>>  + }
>>>>  +
>>>>  + if (!IS_ENABLED(THERMAL_OF))
>>>>  + return 0;
>>>>  +
>>>>  + tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, info,
>>>>  + &sun4i_ts_tz_ops);
>>>>  + if (IS_ERR(tzd))
>>>>  + dev_err(&pdev->dev, "could not register thermal sensor: %ld\n",
>>>>  + PTR_ERR(tzd));
>>>>  +
>>>>  + return PTR_ERR_OR_ZERO(tzd);
>>>>  +}
>>>>  +
>>>>   static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
>>>>                                    struct iio_dev *indio_dev)
>>>>   {
>>>>  @@ -462,6 +549,7 @@ static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
>>>>                   dev_get_drvdata(pdev->dev.parent);
>>>>           int ret;
>>>>
>>>>  + info->no_irq = false;
>>>>           info->regmap = sun4i_gpadc_dev->regmap;
>>>>
>>>>           indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels);
>>>>  @@ -561,7 +649,11 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
>>>>           indio_dev->info = &sun4i_gpadc_iio_info;
>>>>           indio_dev->modes = INDIO_DIRECT_MODE;
>>>>
>>>>  - ret = sun4i_gpadc_probe_mfd(pdev, indio_dev);
>>>>  + if (pdev->dev.of_node)
>>>>  + ret = sun4i_gpadc_probe_dt(pdev, indio_dev);
>>>>  + else
>>>>  + ret = sun4i_gpadc_probe_mfd(pdev, indio_dev);
>>>>  +
>>>>           if (ret)
>>>>                   return ret;
>>>>
>>>>  @@ -580,7 +672,7 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
>>>>           return 0;
>>>>
>>>>   err_map:
>>>>  - if (IS_ENABLED(CONFIG_THERMAL_OF))
>>>>  + if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))
>>>>                   iio_map_array_unregister(indio_dev);
>>>>
>>>>           pm_runtime_put(&pdev->dev);
>>>>  @@ -592,10 +684,11 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
>>>>   static int sun4i_gpadc_remove(struct platform_device *pdev)
>>>>   {
>>>>           struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>>>>  + struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
>>>>
>>>>           pm_runtime_put(&pdev->dev);
>>>>           pm_runtime_disable(&pdev->dev);
>>>>  - if (IS_ENABLED(CONFIG_THERMAL_OF))
>>>>  + if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))
>>>>                   iio_map_array_unregister(indio_dev);
>>>>
>>>>           return 0;
>>>>  @@ -611,6 +704,7 @@ static const struct platform_device_id sun4i_gpadc_id[] = {
>>>>   static struct platform_driver sun4i_gpadc_driver = {
>>>>           .driver = {
>>>>                   .name = "sun4i-gpadc-iio",
>>>>  + .of_match_table = sun4i_gpadc_of_id,
>>>>                   .pm = &sun4i_gpadc_pm_ops,
>>>>           },
>>>>           .id_table = sun4i_gpadc_id,
>>>>  diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
>>>>  index 509e736..139872c 100644
>>>>  --- a/include/linux/mfd/sun4i-gpadc.h
>>>>  +++ b/include/linux/mfd/sun4i-gpadc.h
>>>>  @@ -38,6 +38,10 @@
>>>>   #define SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(x) (GENMASK(3, 0) & BIT(x))
>>>>   #define SUN6I_GPADC_CTRL1_ADC_CHAN_MASK GENMASK(3, 0)
>>>>
>>>>  +/* TP_CTRL1 bits for sun8i SoCs */
>>>>  +#define SUN8I_GPADC_CTRL1_CHOP_TEMP_EN BIT(8)
>>>>  +#define SUN8I_GPADC_CTRL1_GPADC_CALI_EN BIT(7)
>>>>  +
>>>>   #define SUN4I_GPADC_CTRL2 0x08
>>>>
>>>>   #define SUN4I_GPADC_CTRL2_TP_SENSITIVE_ADJUST(x) ((GENMASK(3, 0) & (x)) << 28)
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 




More information about the linux-arm-kernel mailing list