[PATCH v1 2/4] iio: adc: Add support for MediaTek MT6357/8/9 Auxiliary ADC
Andy Shevchenko
andy.shevchenko at gmail.com
Thu May 30 06:34:27 PDT 2024
On Thu, May 30, 2024 at 12:34 PM AngeloGioacchino Del Regno
<angelogioacchino.delregno at collabora.com> wrote:
>
> Add a driver to support reading the Auxiliary ADC IP found in the
> MediaTek MT6357, MT6358 and MT6359 Power Management ICs.
>
> This driver provides multiple ADC channels for system monitoring,
> such as battery voltage, PMIC temperature, PMIC-internal voltage
> regulators temperature, and others.
> ---
Here is no explanation on how this is differ to any of the three
existing drivers? I.o.w. why do we need a brand new one?
...
+ bits.h
> +#include <linux/delay.h>
> +#include <linux/kernel.h>
Why?
+ mod_devicetable.h
> +#include <linux/module.h>
> +#include <linux/of.h>
Why?
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
+ types.h
+ blank line
> +#include <linux/iio/iio.h>
+ Blank line
> +#include <linux/mfd/mt6397/core.h>
...
> +#define PMIC_RG_RESET_VAL (BIT(0) | BIT(3))
In this form it requires a comment explaining each mentioned bit.
> +#define PMIC_AUXADC_ADCx(x) ((x) << 1)
Seems like a useless macro, it occupies much more space than in-place shift.
...
> +#define MT6358_IMP0_CLEAR (BIT(14) | BIT(7))
As per above.
...
> +/**
> + * struct mtk_pmic_auxadc_chan - PMIC AUXADC channel data
> + * @req_idx: Request register number
> + * @req_mask: Bitmask to activate a channel
> + * @num_samples: Number of AUXADC samples for averaging
> + * @r_numerator: Resistance ratio numerator
> + * @r_denominator: Resistance ratio denominator
> + */
> +struct mtk_pmic_auxadc_chan {
> + u8 req_idx;
> + u16 req_mask;
> + u16 num_samples;
> + u8 r_numerator;
> + u8 r_denominator;
Can you add struct u8_fract to the math.h and use it? I will Ack/R the
respective patch.
> +};
...
> +struct mtk_pmic_auxadc_pdata {
> + const struct iio_chan_spec *channels;
> + int num_channels;
Why signed?
> + const struct mtk_pmic_auxadc_chan *desc;
> + const u16 *regs;
> + u16 sec_unlock_key;
> + u8 imp_adc_num;
> + int (*read_imp)(struct mt6359_auxadc *adc_dev, int *vbat, int *ibat);
> +};
...
> +static const u16 mt6357_auxadc_regs[] = {
> + [PMIC_HK_TOP_RST_CON0] = 0xf90,
Can we use the fixed-width values so all of them will look nice and
easy to parse?
> + [PMIC_AUXADC_DCM_CON] = 0x122e,
> + [PMIC_AUXADC_ADC0] = 0x1088,
> + [PMIC_AUXADC_IMP0] = 0x119c,
> + [PMIC_AUXADC_IMP1] = 0x119e,
> + [PMIC_AUXADC_RQST0] = 0x110e,
> + [PMIC_AUXADC_RQST1] = 0x1114,
> +};
...
> +static const u16 mt6358_auxadc_regs[] = {
Ditto.
> + [PMIC_HK_TOP_RST_CON0] = 0xf90,
> + [PMIC_AUXADC_DCM_CON] = 0x1260,
> + [PMIC_AUXADC_ADC0] = 0x1088,
> + [PMIC_AUXADC_IMP0] = 0x1208,
> + [PMIC_AUXADC_IMP1] = 0x120a,
> + [PMIC_AUXADC_RQST0] = 0x1108,
> + [PMIC_AUXADC_RQST1] = 0x110a,
> +};
...
> +static const u16 mt6359_auxadc_regs[] = {
Ditto.
> + [PMIC_FGADC_R_CON0] = 0xd88,
> + [PMIC_HK_TOP_WKEY] = 0xfb4,
> + [PMIC_HK_TOP_RST_CON0] = 0xf90,
> + [PMIC_AUXADC_RQST0] = 0x1108,
> + [PMIC_AUXADC_RQST1] = 0x110a,
> + [PMIC_AUXADC_ADC0] = 0x1088,
> + [PMIC_AUXADC_IMP0] = 0x1208,
> + [PMIC_AUXADC_IMP1] = 0x120a,
> + [PMIC_AUXADC_IMP3] = 0x120e,
> +};
...
> + ret = regmap_read_poll_timeout(adc_dev->regmap, pdata->regs[PMIC_AUXADC_IMP0],
> + val, !!(val & MT6358_IMP0_IRQ_RDY),
> + IMP_POLL_DELAY_US, AUXADC_TIMEOUT_US);
> + if (ret) {
> + mt6358_stop_imp_conv(adc_dev);
> + return ret;
> + }
> +
> + return 0;
if (ret)
foo()
return ret;
...
> + int val_v, ret;
Why is val_v signed?
...
> + int val_v, val_i, ret;
Ditto for all val_*.
...
> + /* If it succeeded, wait for the registers to be populated */
> + usleep_range(IMP_STOP_DELAY_US, IMP_STOP_DELAY_US + 50);
fsleep() ?
...
> + /* Assert ADC reset */
> + regmap_set_bits(regmap, pdata->regs[PMIC_HK_TOP_RST_CON0], PMIC_RG_RESET_VAL);
No required delay in between?
> + /* De-assert ADC reset */
> + regmap_clear_bits(regmap, pdata->regs[PMIC_HK_TOP_RST_CON0], PMIC_RG_RESET_VAL);
...
> + /* Wait until all samples are averaged */
> + usleep_range(desc->num_samples * AUXADC_AVG_TIME_US,
> + (desc->num_samples + 1) * AUXADC_AVG_TIME_US);
fsleep()
...
> + ret = regmap_read_poll_timeout(regmap,
> + (pdata->regs[PMIC_AUXADC_ADC0] +
> + PMIC_AUXADC_ADCx(chan->address)),
Drop unneeded parentheses and possibly make it one line.
> + val, (val & PMIC_AUXADC_RDY_BIT),
Unneeded parentheses.
> + AUXADC_POLL_DELAY_US, AUXADC_TIMEOUT_US);
> + if (ret)
> + return ret;
...
> + mutex_lock(&adc_dev->lock);
Why not use cleanup.h?
...
> +static int mt6359_auxadc_probe(struct platform_device *pdev)
> +{
struct device *dev = &pdev->dev;
> + struct device *mt6397_mfd_dev = pdev->dev.parent;
... = dev->parent;
> + struct mt6359_auxadc *adc_dev;
> + struct iio_dev *indio_dev;
> + struct regmap *regmap;
> + int ret;
> +
> + /* Regmap is from SoC PMIC Wrapper, parent of the mt6397 MFD */
> + regmap = dev_get_regmap(mt6397_mfd_dev->parent, NULL);
> + if (!regmap)
> + return dev_err_probe(&pdev->dev, -ENODEV, "Failed to get regmap\n");
> +
> + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + adc_dev = iio_priv(indio_dev);
> + adc_dev->regmap = regmap;
> + adc_dev->dev = &pdev->dev;
> +
> + adc_dev->pdata = device_get_match_data(&pdev->dev);
> + if (!adc_dev->pdata)
> + return -EINVAL;
> +
> + mutex_init(&adc_dev->lock);
> +
> + mt6359_auxadc_reset(adc_dev);
> +
> + indio_dev->dev.parent = &pdev->dev;
> + indio_dev->name = dev_name(&pdev->dev);
> + indio_dev->info = &mt6359_auxadc_info;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = adc_dev->pdata->channels;
> + indio_dev->num_channels = adc_dev->pdata->num_channels;
> +
> + ret = devm_iio_device_register(&pdev->dev, indio_dev);
> + if (ret < 0)
Why ' < 0' ?
> + return dev_err_probe(&pdev->dev, ret, "failed to register iio device\n");
> +
> + return 0;
> +}
--
With Best Regards,
Andy Shevchenko
More information about the Linux-mediatek
mailing list