[12/12] iio: adc: adi-axi-adc: move to backend framework
Commit Message
From: Nuno Sa <nuno.sa@analog.com>
Move to the IIO backend framework. Devices supported by adi-axi-adc now
register themselves as backend devices.
Signed-off-by: Nuno Sa <nuno.sa@analog.com>
---
drivers/iio/adc/Kconfig | 1 +
drivers/iio/adc/adi-axi-adc.c | 364 ++++++++----------------------------------
2 files changed, 65 insertions(+), 300 deletions(-)
Comments
Hi Nuno,
kernel test robot noticed the following build warnings:
[auto build test WARNING on jic23-iio/togreg]
[also build test WARNING on driver-core/driver-core-testing driver-core/driver-core-next driver-core/driver-core-linus robh/for-next linus/master v6.7-rc2 next-20231121]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Nuno-Sa-via-B4-Relay/driver-core-allow-modifying-device_links-flags/20231121-182010
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link: https://lore.kernel.org/r/20231121-dev-iio-backend-v1-12-6a3d542eba35%40analog.com
patch subject: [PATCH 12/12] iio: adc: adi-axi-adc: move to backend framework
config: i386-randconfig-141-20231122 (https://download.01.org/0day-ci/archive/20231122/202311220748.T1FnZwoy-lkp@intel.com/config)
compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231122/202311220748.T1FnZwoy-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202311220748.T1FnZwoy-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/iio/industrialio-backend.c:123: warning: expecting prototype for iio_backend_chan_enable(). Prototype was for iio_backend_enable() instead
>> drivers/iio/industrialio-backend.c:242: warning: Function parameter or member 'back' not described in 'iio_backend_get_priv'
>> drivers/iio/industrialio-backend.c:274: warning: Function parameter or member 'dev' not described in 'devm_iio_backend_register'
>> drivers/iio/industrialio-backend.c:274: warning: Function parameter or member 'ops' not described in 'devm_iio_backend_register'
>> drivers/iio/industrialio-backend.c:274: warning: Function parameter or member 'priv' not described in 'devm_iio_backend_register'
vim +242 drivers/iio/industrialio-backend.c
67915cd5ae2cc11 Nuno Sa 2023-11-21 114
67915cd5ae2cc11 Nuno Sa 2023-11-21 115 /**
67915cd5ae2cc11 Nuno Sa 2023-11-21 116 * iio_backend_chan_enable - Enable the backend.
67915cd5ae2cc11 Nuno Sa 2023-11-21 117 * @back: Backend device
67915cd5ae2cc11 Nuno Sa 2023-11-21 118 *
67915cd5ae2cc11 Nuno Sa 2023-11-21 119 * RETURNS:
67915cd5ae2cc11 Nuno Sa 2023-11-21 120 * 0 on success, negative error number on failure.
67915cd5ae2cc11 Nuno Sa 2023-11-21 121 */
67915cd5ae2cc11 Nuno Sa 2023-11-21 122 int iio_backend_enable(struct iio_backend *back)
67915cd5ae2cc11 Nuno Sa 2023-11-21 @123 {
67915cd5ae2cc11 Nuno Sa 2023-11-21 124 return iio_backend_op_call(back, enable);
67915cd5ae2cc11 Nuno Sa 2023-11-21 125 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 126 EXPORT_SYMBOL_GPL(iio_backend_enable);
67915cd5ae2cc11 Nuno Sa 2023-11-21 127
67915cd5ae2cc11 Nuno Sa 2023-11-21 128 /**
67915cd5ae2cc11 Nuno Sa 2023-11-21 129 * iio_backend_disable - Disable the backend.
67915cd5ae2cc11 Nuno Sa 2023-11-21 130 * @back: Backend device
67915cd5ae2cc11 Nuno Sa 2023-11-21 131 */
67915cd5ae2cc11 Nuno Sa 2023-11-21 132 void iio_backend_disable(struct iio_backend *back)
67915cd5ae2cc11 Nuno Sa 2023-11-21 133 {
67915cd5ae2cc11 Nuno Sa 2023-11-21 134 iio_backend_void_op_call(back, disable);
67915cd5ae2cc11 Nuno Sa 2023-11-21 135 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 136 EXPORT_SYMBOL_GPL(iio_backend_disable);
67915cd5ae2cc11 Nuno Sa 2023-11-21 137
67915cd5ae2cc11 Nuno Sa 2023-11-21 138 /**
67915cd5ae2cc11 Nuno Sa 2023-11-21 139 * iio_backend_data_format_set - Configure the channel data format
67915cd5ae2cc11 Nuno Sa 2023-11-21 140 * @back: Backend device
67915cd5ae2cc11 Nuno Sa 2023-11-21 141 * @chan: Channel number.
67915cd5ae2cc11 Nuno Sa 2023-11-21 142 * @data: Data format.
67915cd5ae2cc11 Nuno Sa 2023-11-21 143 *
67915cd5ae2cc11 Nuno Sa 2023-11-21 144 * Properly configure a channel with respect to the expected data format. A
67915cd5ae2cc11 Nuno Sa 2023-11-21 145 * @struct iio_backend_data_fmt must be passed with the settings.
67915cd5ae2cc11 Nuno Sa 2023-11-21 146 *
67915cd5ae2cc11 Nuno Sa 2023-11-21 147 * RETURNS:
67915cd5ae2cc11 Nuno Sa 2023-11-21 148 * 0 on success, negative error number on failure
67915cd5ae2cc11 Nuno Sa 2023-11-21 149 */
67915cd5ae2cc11 Nuno Sa 2023-11-21 150 int iio_backend_data_format_set(struct iio_backend *back, unsigned int chan,
67915cd5ae2cc11 Nuno Sa 2023-11-21 151 const struct iio_backend_data_fmt *data)
67915cd5ae2cc11 Nuno Sa 2023-11-21 152 {
67915cd5ae2cc11 Nuno Sa 2023-11-21 153 if (!data || data->type >= IIO_BACKEND_DATA_TYPE_MAX)
67915cd5ae2cc11 Nuno Sa 2023-11-21 154 return -EINVAL;
67915cd5ae2cc11 Nuno Sa 2023-11-21 155
67915cd5ae2cc11 Nuno Sa 2023-11-21 156 return iio_backend_op_call(back, data_format_set, chan, data);
67915cd5ae2cc11 Nuno Sa 2023-11-21 157 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 158 EXPORT_SYMBOL_GPL(iio_backend_data_format_set);
67915cd5ae2cc11 Nuno Sa 2023-11-21 159
67915cd5ae2cc11 Nuno Sa 2023-11-21 160 static void iio_backend_free(struct kref *ref)
67915cd5ae2cc11 Nuno Sa 2023-11-21 161 {
67915cd5ae2cc11 Nuno Sa 2023-11-21 162 struct iio_backend *back = container_of(ref, struct iio_backend, ref);
67915cd5ae2cc11 Nuno Sa 2023-11-21 163
67915cd5ae2cc11 Nuno Sa 2023-11-21 164 kfree(back);
67915cd5ae2cc11 Nuno Sa 2023-11-21 165 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 166
67915cd5ae2cc11 Nuno Sa 2023-11-21 167 static void iio_backend_release(void *arg)
67915cd5ae2cc11 Nuno Sa 2023-11-21 168 {
67915cd5ae2cc11 Nuno Sa 2023-11-21 169 struct iio_backend *back = arg;
67915cd5ae2cc11 Nuno Sa 2023-11-21 170
67915cd5ae2cc11 Nuno Sa 2023-11-21 171 module_put(back->owner);
67915cd5ae2cc11 Nuno Sa 2023-11-21 172 kref_put(&back->ref, iio_backend_free);
67915cd5ae2cc11 Nuno Sa 2023-11-21 173 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 174
67915cd5ae2cc11 Nuno Sa 2023-11-21 175 /**
67915cd5ae2cc11 Nuno Sa 2023-11-21 176 * devm_iio_backend_get - Get a backend device
67915cd5ae2cc11 Nuno Sa 2023-11-21 177 * @dev: Device where to look for the backend.
67915cd5ae2cc11 Nuno Sa 2023-11-21 178 * @name: Backend name.
67915cd5ae2cc11 Nuno Sa 2023-11-21 179 *
67915cd5ae2cc11 Nuno Sa 2023-11-21 180 * Get's the backend associated with @dev.
67915cd5ae2cc11 Nuno Sa 2023-11-21 181 *
67915cd5ae2cc11 Nuno Sa 2023-11-21 182 * RETURNS:
67915cd5ae2cc11 Nuno Sa 2023-11-21 183 * A backend pointer, negative error pointer otherwise.
67915cd5ae2cc11 Nuno Sa 2023-11-21 184 */
67915cd5ae2cc11 Nuno Sa 2023-11-21 185 struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name)
67915cd5ae2cc11 Nuno Sa 2023-11-21 186 {
67915cd5ae2cc11 Nuno Sa 2023-11-21 187 struct fwnode_handle *fwnode;
67915cd5ae2cc11 Nuno Sa 2023-11-21 188 struct iio_backend *back;
67915cd5ae2cc11 Nuno Sa 2023-11-21 189 int index = 0, ret;
67915cd5ae2cc11 Nuno Sa 2023-11-21 190
67915cd5ae2cc11 Nuno Sa 2023-11-21 191 if (name) {
67915cd5ae2cc11 Nuno Sa 2023-11-21 192 index = device_property_match_string(dev, "io-backends-names",
67915cd5ae2cc11 Nuno Sa 2023-11-21 193 name);
67915cd5ae2cc11 Nuno Sa 2023-11-21 194 if (index < 0)
67915cd5ae2cc11 Nuno Sa 2023-11-21 195 return ERR_PTR(index);
67915cd5ae2cc11 Nuno Sa 2023-11-21 196 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 197
67915cd5ae2cc11 Nuno Sa 2023-11-21 198 fwnode = fwnode_find_reference(dev_fwnode(dev), "io-backends", index);
67915cd5ae2cc11 Nuno Sa 2023-11-21 199 if (IS_ERR(fwnode)) {
67915cd5ae2cc11 Nuno Sa 2023-11-21 200 dev_err(dev, "Cannot get Firmware reference\n");
67915cd5ae2cc11 Nuno Sa 2023-11-21 201 return ERR_CAST(fwnode);
67915cd5ae2cc11 Nuno Sa 2023-11-21 202 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 203
67915cd5ae2cc11 Nuno Sa 2023-11-21 204 guard(mutex)(&iio_back_lock);
67915cd5ae2cc11 Nuno Sa 2023-11-21 205 list_for_each_entry(back, &iio_back_list, entry) {
67915cd5ae2cc11 Nuno Sa 2023-11-21 206 struct device_link *link;
67915cd5ae2cc11 Nuno Sa 2023-11-21 207
67915cd5ae2cc11 Nuno Sa 2023-11-21 208 if (!device_match_fwnode(back->dev, fwnode))
67915cd5ae2cc11 Nuno Sa 2023-11-21 209 continue;
67915cd5ae2cc11 Nuno Sa 2023-11-21 210
67915cd5ae2cc11 Nuno Sa 2023-11-21 211 fwnode_handle_put(fwnode);
67915cd5ae2cc11 Nuno Sa 2023-11-21 212 kref_get(&back->ref);
67915cd5ae2cc11 Nuno Sa 2023-11-21 213 if (!try_module_get(back->owner)) {
67915cd5ae2cc11 Nuno Sa 2023-11-21 214 dev_err(dev, "Cannot get module reference\n");
67915cd5ae2cc11 Nuno Sa 2023-11-21 215 return ERR_PTR(-ENODEV);
67915cd5ae2cc11 Nuno Sa 2023-11-21 216 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 217
67915cd5ae2cc11 Nuno Sa 2023-11-21 218 ret = devm_add_action_or_reset(dev, iio_backend_release, back);
67915cd5ae2cc11 Nuno Sa 2023-11-21 219 if (ret)
67915cd5ae2cc11 Nuno Sa 2023-11-21 220 return ERR_PTR(ret);
67915cd5ae2cc11 Nuno Sa 2023-11-21 221
67915cd5ae2cc11 Nuno Sa 2023-11-21 222 link = device_link_add(dev, back->dev,
67915cd5ae2cc11 Nuno Sa 2023-11-21 223 DL_FLAG_AUTOREMOVE_CONSUMER);
67915cd5ae2cc11 Nuno Sa 2023-11-21 224 if (!link)
67915cd5ae2cc11 Nuno Sa 2023-11-21 225 dev_warn(dev, "Could not link to supplier(%s)\n",
67915cd5ae2cc11 Nuno Sa 2023-11-21 226 dev_name(back->dev));
67915cd5ae2cc11 Nuno Sa 2023-11-21 227
67915cd5ae2cc11 Nuno Sa 2023-11-21 228 dev_dbg(dev, "Found backend(%s) device\n", dev_name(back->dev));
67915cd5ae2cc11 Nuno Sa 2023-11-21 229 return back;
67915cd5ae2cc11 Nuno Sa 2023-11-21 230 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 231
67915cd5ae2cc11 Nuno Sa 2023-11-21 232 fwnode_handle_put(fwnode);
67915cd5ae2cc11 Nuno Sa 2023-11-21 233 return ERR_PTR(-EPROBE_DEFER);
67915cd5ae2cc11 Nuno Sa 2023-11-21 234 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 235 EXPORT_SYMBOL_GPL(devm_iio_backend_get);
67915cd5ae2cc11 Nuno Sa 2023-11-21 236
67915cd5ae2cc11 Nuno Sa 2023-11-21 237 /**
67915cd5ae2cc11 Nuno Sa 2023-11-21 238 * iio_backend_get_priv - Get driver private data
67915cd5ae2cc11 Nuno Sa 2023-11-21 239 * @back Backend device
67915cd5ae2cc11 Nuno Sa 2023-11-21 240 */
67915cd5ae2cc11 Nuno Sa 2023-11-21 241 void *iio_backend_get_priv(const struct iio_backend *back)
67915cd5ae2cc11 Nuno Sa 2023-11-21 @242 {
67915cd5ae2cc11 Nuno Sa 2023-11-21 243 return back->priv;
67915cd5ae2cc11 Nuno Sa 2023-11-21 244 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 245 EXPORT_SYMBOL_GPL(iio_backend_get_priv);
67915cd5ae2cc11 Nuno Sa 2023-11-21 246
67915cd5ae2cc11 Nuno Sa 2023-11-21 247 static void iio_backend_unregister(void *arg)
67915cd5ae2cc11 Nuno Sa 2023-11-21 248 {
67915cd5ae2cc11 Nuno Sa 2023-11-21 249 struct iio_backend *back = arg;
67915cd5ae2cc11 Nuno Sa 2023-11-21 250
67915cd5ae2cc11 Nuno Sa 2023-11-21 251 mutex_lock(&iio_back_lock);
67915cd5ae2cc11 Nuno Sa 2023-11-21 252 list_del(&back->entry);
67915cd5ae2cc11 Nuno Sa 2023-11-21 253 mutex_unlock(&iio_back_lock);
67915cd5ae2cc11 Nuno Sa 2023-11-21 254
67915cd5ae2cc11 Nuno Sa 2023-11-21 255 mutex_lock(&back->lock);
67915cd5ae2cc11 Nuno Sa 2023-11-21 256 back->ops = NULL;
67915cd5ae2cc11 Nuno Sa 2023-11-21 257 mutex_unlock(&back->lock);
67915cd5ae2cc11 Nuno Sa 2023-11-21 258 kref_put(&back->ref, iio_backend_free);
67915cd5ae2cc11 Nuno Sa 2023-11-21 259 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 260
67915cd5ae2cc11 Nuno Sa 2023-11-21 261 /**
67915cd5ae2cc11 Nuno Sa 2023-11-21 262 * devm_iio_backend_register - Register a new backend device
67915cd5ae2cc11 Nuno Sa 2023-11-21 263 * @dev Backend device being registered.
67915cd5ae2cc11 Nuno Sa 2023-11-21 264 * @ops Backend ops
67915cd5ae2cc11 Nuno Sa 2023-11-21 265 * @priv Device private data.
67915cd5ae2cc11 Nuno Sa 2023-11-21 266 *
67915cd5ae2cc11 Nuno Sa 2023-11-21 267 * @ops and @priv are both mandatory. Not providing them results in -EINVAL.
67915cd5ae2cc11 Nuno Sa 2023-11-21 268 *
67915cd5ae2cc11 Nuno Sa 2023-11-21 269 * RETURNS:
67915cd5ae2cc11 Nuno Sa 2023-11-21 270 * 0 on success, negative error number on failure.
67915cd5ae2cc11 Nuno Sa 2023-11-21 271 */
67915cd5ae2cc11 Nuno Sa 2023-11-21 272 int devm_iio_backend_register(struct device *dev,
67915cd5ae2cc11 Nuno Sa 2023-11-21 273 const struct iio_backend_ops *ops, void *priv)
67915cd5ae2cc11 Nuno Sa 2023-11-21 @274 {
67915cd5ae2cc11 Nuno Sa 2023-11-21 275 struct iio_backend *back;
67915cd5ae2cc11 Nuno Sa 2023-11-21 276
67915cd5ae2cc11 Nuno Sa 2023-11-21 277 if (!ops || !priv) {
67915cd5ae2cc11 Nuno Sa 2023-11-21 278 dev_err(dev, "No backend ops or private data given\n");
67915cd5ae2cc11 Nuno Sa 2023-11-21 279 return -EINVAL;
67915cd5ae2cc11 Nuno Sa 2023-11-21 280 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 281
67915cd5ae2cc11 Nuno Sa 2023-11-21 282 back = kzalloc(sizeof(*back), GFP_KERNEL);
67915cd5ae2cc11 Nuno Sa 2023-11-21 283 if (!back)
67915cd5ae2cc11 Nuno Sa 2023-11-21 284 return -ENOMEM;
67915cd5ae2cc11 Nuno Sa 2023-11-21 285
67915cd5ae2cc11 Nuno Sa 2023-11-21 286 kref_init(&back->ref);
67915cd5ae2cc11 Nuno Sa 2023-11-21 287 mutex_init(&back->lock);
67915cd5ae2cc11 Nuno Sa 2023-11-21 288 back->ops = ops;
67915cd5ae2cc11 Nuno Sa 2023-11-21 289 back->owner = dev->driver->owner;
67915cd5ae2cc11 Nuno Sa 2023-11-21 290 back->dev = dev;
67915cd5ae2cc11 Nuno Sa 2023-11-21 291 back->priv = priv;
67915cd5ae2cc11 Nuno Sa 2023-11-21 292 mutex_lock(&iio_back_lock);
67915cd5ae2cc11 Nuno Sa 2023-11-21 293 list_add(&back->entry, &iio_back_list);
67915cd5ae2cc11 Nuno Sa 2023-11-21 294 mutex_unlock(&iio_back_lock);
67915cd5ae2cc11 Nuno Sa 2023-11-21 295
67915cd5ae2cc11 Nuno Sa 2023-11-21 296 return devm_add_action_or_reset(dev, iio_backend_unregister, back);
67915cd5ae2cc11 Nuno Sa 2023-11-21 297 }
67915cd5ae2cc11 Nuno Sa 2023-11-21 298 EXPORT_SYMBOL_GPL(devm_iio_backend_register);
67915cd5ae2cc11 Nuno Sa 2023-11-21 299
Hi Nuno,
kernel test robot noticed the following build warnings:
[auto build test WARNING on jic23-iio/togreg]
[also build test WARNING on driver-core/driver-core-testing driver-core/driver-core-next driver-core/driver-core-linus robh/for-next linus/master v6.7-rc2 next-20231124]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Nuno-Sa-via-B4-Relay/driver-core-allow-modifying-device_links-flags/20231121-182010
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link: https://lore.kernel.org/r/20231121-dev-iio-backend-v1-12-6a3d542eba35%40analog.com
patch subject: [PATCH 12/12] iio: adc: adi-axi-adc: move to backend framework
config: arm-randconfig-r081-20231123 (https://download.01.org/0day-ci/archive/20231125/202311251430.QfOfg5Ws-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20231125/202311251430.QfOfg5Ws-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202311251430.QfOfg5Ws-lkp@intel.com/
smatch warnings:
drivers/iio/adc/adi-axi-adc.c:64 axi_adc_enable() warn: inconsistent indenting
vim +64 drivers/iio/adc/adi-axi-adc.c
58
59 static int axi_adc_enable(struct iio_backend *back)
60 {
61 struct adi_axi_adc_state *st = iio_backend_get_priv(back);
62 int ret;
63
> 64 ret = regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
65 ADI_AXI_REG_RSTN_MMCM_RSTN);
66 if (ret)
67 return ret;
68
69 fsleep(10);
70 return regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
71 ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
72 }
73
On Tue, Nov 21, 2023 at 4:17 AM Nuno Sa via B4 Relay
<devnull+nuno.sa.analog.com@kernel.org> wrote:
>
> From: Nuno Sa <nuno.sa@analog.com>
>
> Move to the IIO backend framework. Devices supported by adi-axi-adc now
> register themselves as backend devices.
>
> Signed-off-by: Nuno Sa <nuno.sa@analog.com>
> ---
> drivers/iio/adc/Kconfig | 1 +
> drivers/iio/adc/adi-axi-adc.c | 364 ++++++++----------------------------------
> 2 files changed, 65 insertions(+), 300 deletions(-)
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index af56df63beff..cc42a3399c63 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -292,6 +292,7 @@ config ADI_AXI_ADC
> select IIO_BUFFER
> select IIO_BUFFER_HW_CONSUMER
> select IIO_BUFFER_DMAENGINE
> + select IIO_BACKEND
> depends on HAS_IOMEM
> depends on OF
> help
> diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
> index c247ff1541d2..b2ab2c119efa 100644
> --- a/drivers/iio/adc/adi-axi-adc.c
> +++ b/drivers/iio/adc/adi-axi-adc.c
<snip>
> @@ -390,37 +166,23 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> - if (cl->info->version > ver) {
> + if (*expected_ver > ver) {
> dev_err(&pdev->dev,
> "IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
> - ADI_AXI_PCORE_VER_MAJOR(cl->info->version),
> - ADI_AXI_PCORE_VER_MINOR(cl->info->version),
> - ADI_AXI_PCORE_VER_PATCH(cl->info->version),
> + ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
> + ADI_AXI_PCORE_VER_MINOR(*expected_ver),
> + ADI_AXI_PCORE_VER_PATCH(*expected_ver),
> ADI_AXI_PCORE_VER_MAJOR(ver),
> ADI_AXI_PCORE_VER_MINOR(ver),
> ADI_AXI_PCORE_VER_PATCH(ver));
> return -ENODEV;
> }
>
> - indio_dev->info = &adi_axi_adc_info;
> - indio_dev->name = "adi-axi-adc";
> - indio_dev->modes = INDIO_DIRECT_MODE;
> - indio_dev->num_channels = conv->chip_info->num_channels;
> - indio_dev->channels = conv->chip_info->channels;
> -
> - ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
> + ret = devm_iio_backend_register(&pdev->dev, &adi_axi_adc_generic, st);
> if (ret)
> return ret;
>
> - ret = adi_axi_adc_setup_channels(&pdev->dev, st);
> - if (ret)
> - return ret;
> -
> - ret = devm_iio_device_register(&pdev->dev, indio_dev);
> - if (ret)
> - return ret;
> -
> - dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%c) probed\n",
> + dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%d) probed\n",
Was this format change intentional? There are other places above where
%c is still used.
> ADI_AXI_PCORE_VER_MAJOR(ver),
> ADI_AXI_PCORE_VER_MINOR(ver),
> ADI_AXI_PCORE_VER_PATCH(ver));
> @@ -428,6 +190,8 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
> return 0;
> }
>
> +static unsigned int adi_axi_adc_10_0_a_info = ADI_AXI_PCORE_VER(10, 0, 'a');
> +
> /* Match table for of_platform binding */
> static const struct of_device_id adi_axi_adc_of_match[] = {
> { .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },
>
> --
> 2.42.1
>
>
On Thu, 2023-11-30 at 17:33 -0600, David Lechner wrote:
> On Tue, Nov 21, 2023 at 4:17 AM Nuno Sa via B4 Relay
> <devnull+nuno.sa.analog.com@kernel.org> wrote:
> >
> > From: Nuno Sa <nuno.sa@analog.com>
> >
> > Move to the IIO backend framework. Devices supported by adi-axi-adc now
> > register themselves as backend devices.
> >
> > Signed-off-by: Nuno Sa <nuno.sa@analog.com>
> > ---
> > drivers/iio/adc/Kconfig | 1 +
> > drivers/iio/adc/adi-axi-adc.c | 364 ++++++++----------------------------------
> > 2 files changed, 65 insertions(+), 300 deletions(-)
> >
> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> > index af56df63beff..cc42a3399c63 100644
> > --- a/drivers/iio/adc/Kconfig
> > +++ b/drivers/iio/adc/Kconfig
> > @@ -292,6 +292,7 @@ config ADI_AXI_ADC
> > select IIO_BUFFER
> > select IIO_BUFFER_HW_CONSUMER
> > select IIO_BUFFER_DMAENGINE
> > + select IIO_BACKEND
> > depends on HAS_IOMEM
> > depends on OF
> > help
> > diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
> > index c247ff1541d2..b2ab2c119efa 100644
> > --- a/drivers/iio/adc/adi-axi-adc.c
> > +++ b/drivers/iio/adc/adi-axi-adc.c
>
> <snip>
>
> > @@ -390,37 +166,23 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
> > if (ret)
> > return ret;
> >
> > - if (cl->info->version > ver) {
> > + if (*expected_ver > ver) {
> > dev_err(&pdev->dev,
> > "IP core version is too old. Expected %d.%.2d.%c,
> > Reported %d.%.2d.%c\n",
> > - ADI_AXI_PCORE_VER_MAJOR(cl->info->version),
> > - ADI_AXI_PCORE_VER_MINOR(cl->info->version),
> > - ADI_AXI_PCORE_VER_PATCH(cl->info->version),
> > + ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
> > + ADI_AXI_PCORE_VER_MINOR(*expected_ver),
> > + ADI_AXI_PCORE_VER_PATCH(*expected_ver),
> > ADI_AXI_PCORE_VER_MAJOR(ver),
> > ADI_AXI_PCORE_VER_MINOR(ver),
> > ADI_AXI_PCORE_VER_PATCH(ver));
> > return -ENODEV;
> > }
> >
> > - indio_dev->info = &adi_axi_adc_info;
> > - indio_dev->name = "adi-axi-adc";
> > - indio_dev->modes = INDIO_DIRECT_MODE;
> > - indio_dev->num_channels = conv->chip_info->num_channels;
> > - indio_dev->channels = conv->chip_info->channels;
> > -
> > - ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
> > + ret = devm_iio_backend_register(&pdev->dev, &adi_axi_adc_generic, st);
> > if (ret)
> > return ret;
> >
> > - ret = adi_axi_adc_setup_channels(&pdev->dev, st);
> > - if (ret)
> > - return ret;
> > -
> > - ret = devm_iio_device_register(&pdev->dev, indio_dev);
> > - if (ret)
> > - return ret;
> > -
> > - dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%c) probed\n",
> > + dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%d) probed\n",
>
> Was this format change intentional? There are other places above where
> %c is still used.
>
Yes, the output was weird with %c. I guess something changed... Hmm need to look at
the other places.
- Nuno Sá
>
@@ -292,6 +292,7 @@ config ADI_AXI_ADC
select IIO_BUFFER
select IIO_BUFFER_HW_CONSUMER
select IIO_BUFFER_DMAENGINE
+ select IIO_BACKEND
depends on HAS_IOMEM
depends on OF
help
@@ -17,13 +17,9 @@
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/buffer-dmaengine.h>
-
#include <linux/fpga/adi-axi-common.h>
-#include <linux/iio/adc/adi-axi-adc.h>
+#include <linux/iio/backend.h>
+
/*
* Register definitions:
@@ -44,6 +40,7 @@
#define ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR BIT(10)
#define ADI_AXI_REG_CHAN_CTRL_IQCOR_EN BIT(9)
#define ADI_AXI_REG_CHAN_CTRL_DCFILT_EN BIT(8)
+#define ADI_AXI_REG_CHAN_CTRL_FMT_MASK GENMASK(6, 4)
#define ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT BIT(6)
#define ADI_AXI_REG_CHAN_CTRL_FMT_TYPE BIT(5)
#define ADI_AXI_REG_CHAN_CTRL_FMT_EN BIT(4)
@@ -55,286 +52,67 @@
ADI_AXI_REG_CHAN_CTRL_FMT_EN | \
ADI_AXI_REG_CHAN_CTRL_ENABLE)
-struct adi_axi_adc_core_info {
- unsigned int version;
-};
-
struct adi_axi_adc_state {
- struct mutex lock;
-
- struct adi_axi_adc_client *client;
struct regmap *regmap;
};
-struct adi_axi_adc_client {
- struct list_head entry;
- struct adi_axi_adc_conv conv;
- struct adi_axi_adc_state *state;
- struct device *dev;
- const struct adi_axi_adc_core_info *info;
-};
-
-static LIST_HEAD(registered_clients);
-static DEFINE_MUTEX(registered_clients_lock);
-
-static struct adi_axi_adc_client *conv_to_client(struct adi_axi_adc_conv *conv)
-{
- return container_of(conv, struct adi_axi_adc_client, conv);
-}
-
-void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
-{
- struct adi_axi_adc_client *cl = conv_to_client(conv);
-
- return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client),
- IIO_DMA_MINALIGN);
-}
-EXPORT_SYMBOL_NS_GPL(adi_axi_adc_conv_priv, IIO_ADI_AXI);
-
-static int adi_axi_adc_config_dma_buffer(struct device *dev,
- struct iio_dev *indio_dev)
-{
- const char *dma_name;
-
- if (!device_property_present(dev, "dmas"))
- return 0;
-
- if (device_property_read_string(dev, "dma-names", &dma_name))
- dma_name = "rx";
-
- return devm_iio_dmaengine_buffer_setup(indio_dev->dev.parent,
- indio_dev, dma_name);
-}
-
-static int adi_axi_adc_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2, long mask)
-{
- struct adi_axi_adc_state *st = iio_priv(indio_dev);
- struct adi_axi_adc_conv *conv = &st->client->conv;
-
- if (!conv->read_raw)
- return -EOPNOTSUPP;
-
- return conv->read_raw(conv, chan, val, val2, mask);
-}
-
-static int adi_axi_adc_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val, int val2, long mask)
-{
- struct adi_axi_adc_state *st = iio_priv(indio_dev);
- struct adi_axi_adc_conv *conv = &st->client->conv;
-
- if (!conv->write_raw)
- return -EOPNOTSUPP;
-
- return conv->write_raw(conv, chan, val, val2, mask);
-}
-
-static int adi_axi_adc_read_avail(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- const int **vals, int *type, int *length,
- long mask)
-{
- struct adi_axi_adc_state *st = iio_priv(indio_dev);
- struct adi_axi_adc_conv *conv = &st->client->conv;
-
- if (!conv->read_avail)
- return -EOPNOTSUPP;
-
- return conv->read_avail(conv, chan, vals, type, length, mask);
-}
-
-static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev,
- const unsigned long *scan_mask)
-{
- struct adi_axi_adc_state *st = iio_priv(indio_dev);
- struct adi_axi_adc_conv *conv = &st->client->conv;
- unsigned int i;
- int ret;
-
- for (i = 0; i < conv->chip_info->num_channels; i++) {
- if (test_bit(i, scan_mask))
- ret = regmap_set_bits(st->regmap,
- ADI_AXI_REG_CHAN_CTRL(i),
- ADI_AXI_REG_CHAN_CTRL_ENABLE);
- else
- ret = regmap_clear_bits(st->regmap,
- ADI_AXI_REG_CHAN_CTRL(i),
- ADI_AXI_REG_CHAN_CTRL_ENABLE);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static struct adi_axi_adc_conv *adi_axi_adc_conv_register(struct device *dev,
- size_t sizeof_priv)
-{
- struct adi_axi_adc_client *cl;
- size_t alloc_size;
-
- alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_DMA_MINALIGN);
- if (sizeof_priv)
- alloc_size += ALIGN(sizeof_priv, IIO_DMA_MINALIGN);
-
- cl = kzalloc(alloc_size, GFP_KERNEL);
- if (!cl)
- return ERR_PTR(-ENOMEM);
-
- mutex_lock(®istered_clients_lock);
-
- cl->dev = get_device(dev);
-
- list_add_tail(&cl->entry, ®istered_clients);
-
- mutex_unlock(®istered_clients_lock);
-
- return &cl->conv;
-}
-
-static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv)
-{
- struct adi_axi_adc_client *cl = conv_to_client(conv);
-
- mutex_lock(®istered_clients_lock);
-
- list_del(&cl->entry);
- put_device(cl->dev);
-
- mutex_unlock(®istered_clients_lock);
-
- kfree(cl);
-}
-
-static void devm_adi_axi_adc_conv_release(void *conv)
-{
- adi_axi_adc_conv_unregister(conv);
-}
-
-struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,
- size_t sizeof_priv)
+static int axi_adc_enable(struct iio_backend *back)
{
- struct adi_axi_adc_conv *conv;
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
int ret;
- conv = adi_axi_adc_conv_register(dev, sizeof_priv);
- if (IS_ERR(conv))
- return conv;
-
- ret = devm_add_action_or_reset(dev, devm_adi_axi_adc_conv_release,
- conv);
+ ret = regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
+ ADI_AXI_REG_RSTN_MMCM_RSTN);
if (ret)
- return ERR_PTR(ret);
+ return ret;
- return conv;
+ fsleep(10);
+ return regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
+ ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
}
-EXPORT_SYMBOL_NS_GPL(devm_adi_axi_adc_conv_register, IIO_ADI_AXI);
-static const struct iio_info adi_axi_adc_info = {
- .read_raw = &adi_axi_adc_read_raw,
- .write_raw = &adi_axi_adc_write_raw,
- .update_scan_mode = &adi_axi_adc_update_scan_mode,
- .read_avail = &adi_axi_adc_read_avail,
-};
-
-static const struct adi_axi_adc_core_info adi_axi_adc_10_0_a_info = {
- .version = ADI_AXI_PCORE_VER(10, 0, 'a'),
-};
-
-static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)
+static void axi_adc_disable(struct iio_backend *back)
{
- const struct adi_axi_adc_core_info *info;
- struct adi_axi_adc_client *cl;
- struct device_node *cln;
-
- info = of_device_get_match_data(dev);
- if (!info)
- return ERR_PTR(-ENODEV);
-
- cln = of_parse_phandle(dev->of_node, "adi,adc-dev", 0);
- if (!cln) {
- dev_err(dev, "No 'adi,adc-dev' node defined\n");
- return ERR_PTR(-ENODEV);
- }
-
- mutex_lock(®istered_clients_lock);
-
- list_for_each_entry(cl, ®istered_clients, entry) {
- if (!cl->dev)
- continue;
-
- if (cl->dev->of_node != cln)
- continue;
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
- if (!try_module_get(cl->dev->driver->owner)) {
- mutex_unlock(®istered_clients_lock);
- of_node_put(cln);
- return ERR_PTR(-ENODEV);
- }
-
- get_device(cl->dev);
- cl->info = info;
- mutex_unlock(®istered_clients_lock);
- of_node_put(cln);
- return cl;
- }
-
- mutex_unlock(®istered_clients_lock);
- of_node_put(cln);
-
- return ERR_PTR(-EPROBE_DEFER);
+ regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
}
-static int adi_axi_adc_setup_channels(struct device *dev,
- struct adi_axi_adc_state *st)
+static int axi_adc_data_format_set(struct iio_backend *back, unsigned int chan,
+ const struct iio_backend_data_fmt *data)
{
- struct adi_axi_adc_conv *conv = &st->client->conv;
- int i, ret;
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+ u32 val;
- if (conv->preenable_setup) {
- ret = conv->preenable_setup(conv);
- if (ret)
- return ret;
- }
+ if (!data->enable)
+ return regmap_clear_bits(st->regmap,
+ ADI_AXI_REG_CHAN_CTRL(chan),
+ ADI_AXI_REG_CHAN_CTRL_FMT_EN);
- for (i = 0; i < conv->chip_info->num_channels; i++) {
- ret = regmap_write(st->regmap, ADI_AXI_REG_CHAN_CTRL(i),
- ADI_AXI_REG_CHAN_CTRL_DEFAULTS);
- if (ret)
- return ret;
- }
+ val = FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_EN, true);
+ if (data->sign_extend)
+ val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT, true);
+ if (data->type == IIO_BACKEND_OFFSET_BINARY)
+ val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_TYPE, true);
- return 0;
+ return regmap_update_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
+ ADI_AXI_REG_CHAN_CTRL_FMT_MASK, val);
}
-static int axi_adc_reset(struct adi_axi_adc_state *st)
+static int axi_adc_chan_enable(struct iio_backend *back, unsigned int chan)
{
- int ret;
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
- ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
- if (ret)
- return ret;
-
- mdelay(10);
- ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN,
- ADI_AXI_REG_RSTN_MMCM_RSTN);
- if (ret)
- return ret;
-
- mdelay(10);
- return regmap_write(st->regmap, ADI_AXI_REG_RSTN,
- ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
+ return regmap_set_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
+ ADI_AXI_REG_CHAN_CTRL_ENABLE);
}
-static void adi_axi_adc_cleanup(void *data)
+static int axi_adc_chan_disable(struct iio_backend *back, unsigned int chan)
{
- struct adi_axi_adc_client *cl = data;
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
- put_device(cl->dev);
- module_put(cl->dev->driver->owner);
+ return regmap_clear_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
+ ADI_AXI_REG_CHAN_CTRL_ENABLE);
}
static const struct regmap_config axi_adc_regmap_config = {
@@ -344,33 +122,25 @@ static const struct regmap_config axi_adc_regmap_config = {
.max_register = 0x0800,
};
+static const struct iio_backend_ops adi_axi_adc_generic = {
+ .enable = axi_adc_enable,
+ .disable = axi_adc_disable,
+ .data_format_set = axi_adc_data_format_set,
+ .chan_enable = axi_adc_chan_enable,
+ .chan_disable = axi_adc_chan_disable,
+};
+
static int adi_axi_adc_probe(struct platform_device *pdev)
{
- struct adi_axi_adc_conv *conv;
- struct iio_dev *indio_dev;
- struct adi_axi_adc_client *cl;
struct adi_axi_adc_state *st;
void __iomem *base;
- unsigned int ver;
+ unsigned int ver, *expected_ver;
int ret;
- cl = adi_axi_adc_attach_client(&pdev->dev);
- if (IS_ERR(cl))
- return PTR_ERR(cl);
-
- ret = devm_add_action_or_reset(&pdev->dev, adi_axi_adc_cleanup, cl);
- if (ret)
- return ret;
-
- indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
- if (indio_dev == NULL)
+ st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
+ if (!st)
return -ENOMEM;
- st = iio_priv(indio_dev);
- st->client = cl;
- cl->state = st;
- mutex_init(&st->lock);
-
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
@@ -380,9 +150,15 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
if (IS_ERR(st->regmap))
return PTR_ERR(st->regmap);
- conv = &st->client->conv;
+ expected_ver = (unsigned int *)device_get_match_data(&pdev->dev);
+ if (!expected_ver)
+ return -ENODEV;
- ret = axi_adc_reset(st);
+ /*
+ * Force disable the core. Up to the frontend to enable us. And we can
+ * still read/write registers...
+ */
+ ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
if (ret)
return ret;
@@ -390,37 +166,23 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (cl->info->version > ver) {
+ if (*expected_ver > ver) {
dev_err(&pdev->dev,
"IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
- ADI_AXI_PCORE_VER_MAJOR(cl->info->version),
- ADI_AXI_PCORE_VER_MINOR(cl->info->version),
- ADI_AXI_PCORE_VER_PATCH(cl->info->version),
+ ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
+ ADI_AXI_PCORE_VER_MINOR(*expected_ver),
+ ADI_AXI_PCORE_VER_PATCH(*expected_ver),
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
ADI_AXI_PCORE_VER_PATCH(ver));
return -ENODEV;
}
- indio_dev->info = &adi_axi_adc_info;
- indio_dev->name = "adi-axi-adc";
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->num_channels = conv->chip_info->num_channels;
- indio_dev->channels = conv->chip_info->channels;
-
- ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
+ ret = devm_iio_backend_register(&pdev->dev, &adi_axi_adc_generic, st);
if (ret)
return ret;
- ret = adi_axi_adc_setup_channels(&pdev->dev, st);
- if (ret)
- return ret;
-
- ret = devm_iio_device_register(&pdev->dev, indio_dev);
- if (ret)
- return ret;
-
- dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%c) probed\n",
+ dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%d) probed\n",
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
ADI_AXI_PCORE_VER_PATCH(ver));
@@ -428,6 +190,8 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
return 0;
}
+static unsigned int adi_axi_adc_10_0_a_info = ADI_AXI_PCORE_VER(10, 0, 'a');
+
/* Match table for of_platform binding */
static const struct of_device_id adi_axi_adc_of_match[] = {
{ .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },