1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Generic sigma delta modulator driver 4 * 5 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 6 * Author: Arnaud Pouliquen <arnaud.pouliquen@st.com>. 7 */ 8 9 #include <linux/iio/backend.h> 10 #include <linux/iio/iio.h> 11 #include <linux/iio/triggered_buffer.h> 12 #include <linux/module.h> 13 #include <linux/mod_devicetable.h> 14 #include <linux/platform_device.h> 15 #include <linux/property.h> 16 #include <linux/regulator/consumer.h> 17 18 static const struct iio_info iio_sd_mod_iio_info; 19 20 static const struct iio_chan_spec iio_sd_mod_ch = { 21 .type = IIO_VOLTAGE, 22 .indexed = 1, 23 .scan_type = { 24 .sign = 'u', 25 .realbits = 1, 26 .shift = 0, 27 }, 28 }; 29 30 struct iio_sd_backend_priv { 31 struct regulator *vref; 32 int vref_mv; 33 }; 34 35 static int iio_sd_mod_enable(struct iio_backend *backend) 36 { 37 struct iio_sd_backend_priv *priv = iio_backend_get_priv(backend); 38 39 if (priv->vref) 40 return regulator_enable(priv->vref); 41 42 return 0; 43 }; 44 45 static void iio_sd_mod_disable(struct iio_backend *backend) 46 { 47 struct iio_sd_backend_priv *priv = iio_backend_get_priv(backend); 48 49 if (priv->vref) 50 regulator_disable(priv->vref); 51 }; 52 53 static int iio_sd_mod_read(struct iio_backend *backend, struct iio_chan_spec const *chan, int *val, 54 int *val2, long mask) 55 { 56 struct iio_sd_backend_priv *priv = iio_backend_get_priv(backend); 57 58 switch (mask) { 59 case IIO_CHAN_INFO_SCALE: 60 *val = priv->vref_mv; 61 return IIO_VAL_INT; 62 63 case IIO_CHAN_INFO_OFFSET: 64 *val = 0; 65 return IIO_VAL_INT; 66 } 67 68 return -EOPNOTSUPP; 69 }; 70 71 static const struct iio_backend_ops sd_backend_ops = { 72 .enable = iio_sd_mod_enable, 73 .disable = iio_sd_mod_disable, 74 .read_raw = iio_sd_mod_read, 75 }; 76 77 static const struct iio_backend_info sd_backend_info = { 78 .name = "sd-modulator", 79 .ops = &sd_backend_ops, 80 }; 81 82 static int iio_sd_mod_register(struct platform_device *pdev) 83 { 84 struct device *dev = &pdev->dev; 85 struct iio_dev *iio; 86 87 iio = devm_iio_device_alloc(dev, 0); 88 if (!iio) 89 return -ENOMEM; 90 91 iio->name = dev_name(dev); 92 iio->info = &iio_sd_mod_iio_info; 93 iio->modes = INDIO_BUFFER_HARDWARE; 94 95 iio->num_channels = 1; 96 iio->channels = &iio_sd_mod_ch; 97 98 platform_set_drvdata(pdev, iio); 99 100 return devm_iio_device_register(&pdev->dev, iio); 101 } 102 103 static int iio_sd_mod_probe(struct platform_device *pdev) 104 { 105 struct device *dev = &pdev->dev; 106 struct regulator *vref; 107 struct iio_sd_backend_priv *priv; 108 int ret; 109 110 /* If sd modulator is not defined as an IIO backend device, fallback to legacy */ 111 if (!device_property_present(dev, "#io-backend-cells")) 112 return iio_sd_mod_register(pdev); 113 114 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 115 if (!priv) 116 return -ENOMEM; 117 118 /* 119 * Get regulator reference if any, but don't enable regulator right now. 120 * Rely on enable and disable callbacks to manage regulator power. 121 */ 122 vref = devm_regulator_get_optional(dev, "vref"); 123 if (IS_ERR(vref)) { 124 if (PTR_ERR(vref) != -ENODEV) 125 return dev_err_probe(dev, PTR_ERR(vref), "Failed to get vref\n"); 126 } else { 127 /* 128 * Retrieve voltage right now, as regulator_get_voltage() provides it whatever 129 * the state of the regulator. 130 */ 131 ret = regulator_get_voltage(vref); 132 if (ret < 0) 133 return ret; 134 135 priv->vref = vref; 136 priv->vref_mv = ret / 1000; 137 } 138 139 return devm_iio_backend_register(&pdev->dev, &sd_backend_info, priv); 140 }; 141 142 static const struct of_device_id sd_adc_of_match[] = { 143 { .compatible = "sd-modulator" }, 144 { .compatible = "ads1201" }, 145 { } 146 }; 147 MODULE_DEVICE_TABLE(of, sd_adc_of_match); 148 149 static struct platform_driver iio_sd_mod_adc = { 150 .driver = { 151 .name = "iio_sd_adc_mod", 152 .of_match_table = sd_adc_of_match, 153 }, 154 .probe = iio_sd_mod_probe, 155 }; 156 157 module_platform_driver(iio_sd_mod_adc); 158 159 MODULE_DESCRIPTION("Basic sigma delta modulator"); 160 MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); 161 MODULE_LICENSE("GPL v2"); 162 MODULE_IMPORT_NS(IIO_BACKEND); 163