iio: adc: rockchip_saradc: add voltage notifier so get referenced voltage once at...
authorDavid Wu <david.wu@rock-chips.com>
Tue, 10 Aug 2021 01:10:07 +0000 (09:10 +0800)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sun, 15 Aug 2021 15:58:37 +0000 (16:58 +0100)
Add voltage notifier, no need to query regulator voltage for
every saradc read, just get regulator voltage once at probe.

Signed-off-by: David Wu <david.wu@rock-chips.com>
Signed-off-by: Simon Xue <xxm@rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Link: https://lore.kernel.org/r/20210810011007.54066-1-xxm@rock-chips.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/rockchip_saradc.c

index f3eb8d2e50dc3638843be39a6d2b09bff9e4538d..a237fe469a30cf2a87773396b212be6a4aaee8ba 100644 (file)
@@ -49,10 +49,12 @@ struct rockchip_saradc {
        struct clk              *clk;
        struct completion       completion;
        struct regulator        *vref;
+       int                     uv_vref;
        struct reset_control    *reset;
        const struct rockchip_saradc_data *data;
        u16                     last_val;
        const struct iio_chan_spec *last_chan;
+       struct notifier_block nb;
 };
 
 static void rockchip_saradc_power_down(struct rockchip_saradc *info)
@@ -105,13 +107,7 @@ static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
                mutex_unlock(&indio_dev->mlock);
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SCALE:
-               ret = regulator_get_voltage(info->vref);
-               if (ret < 0) {
-                       dev_err(&indio_dev->dev, "failed to get voltage\n");
-                       return ret;
-               }
-
-               *val = ret / 1000;
+               *val = info->uv_vref / 1000;
                *val2 = chan->scan_type.realbits;
                return IIO_VAL_FRACTIONAL_LOG2;
        default:
@@ -298,6 +294,26 @@ out:
        return IRQ_HANDLED;
 }
 
+static int rockchip_saradc_volt_notify(struct notifier_block *nb,
+                                                  unsigned long event,
+                                                  void *data)
+{
+       struct rockchip_saradc *info =
+                       container_of(nb, struct rockchip_saradc, nb);
+
+       if (event & REGULATOR_EVENT_VOLTAGE_CHANGE)
+               info->uv_vref = (unsigned long)data;
+
+       return NOTIFY_OK;
+}
+
+static void rockchip_saradc_regulator_unreg_notifier(void *data)
+{
+       struct rockchip_saradc *info = data;
+
+       regulator_unregister_notifier(info->vref, &info->nb);
+}
+
 static int rockchip_saradc_probe(struct platform_device *pdev)
 {
        struct rockchip_saradc *info = NULL;
@@ -410,6 +426,12 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       ret = regulator_get_voltage(info->vref);
+       if (ret < 0)
+               return ret;
+
+       info->uv_vref = ret;
+
        ret = clk_prepare_enable(info->pclk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to enable pclk\n");
@@ -450,6 +472,17 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       info->nb.notifier_call = rockchip_saradc_volt_notify;
+       ret = regulator_register_notifier(info->vref, &info->nb);
+       if (ret)
+               return ret;
+
+       ret = devm_add_action_or_reset(&pdev->dev,
+                                      rockchip_saradc_regulator_unreg_notifier,
+                                      info);
+       if (ret)
+               return ret;
+
        return devm_iio_device_register(&pdev->dev, indio_dev);
 }