On Thu, May 30, 2024 at 12:34 PM AngeloGioacchino Del Regno
<angelogioacchino.delregno@xxxxxxxxxxxxx> 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' ?