| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2014-2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de> |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify it under |
|---|
| 5 | | - * the terms of the GNU General Public License version 2 as published by the |
|---|
| 6 | | - * Free Software Foundation. |
|---|
| 7 | 4 | * |
|---|
| 8 | 5 | * This is the driver for the imx25 GCQ (Generic Conversion Queue) |
|---|
| 9 | 6 | * connected to the imx25 ADC. |
|---|
| .. | .. |
|---|
| 43 | 40 | int irq; |
|---|
| 44 | 41 | struct regulator *vref[4]; |
|---|
| 45 | 42 | u32 channel_vref_mv[MX25_NUM_CFGS]; |
|---|
| 43 | + /* |
|---|
| 44 | + * Lock to protect the device state during a potential concurrent |
|---|
| 45 | + * read access from userspace. Reading a raw value requires a sequence |
|---|
| 46 | + * of register writes, then a wait for a completion callback, |
|---|
| 47 | + * and finally a register read, during which userspace could issue |
|---|
| 48 | + * another read request. This lock protects a read access from |
|---|
| 49 | + * ocurring before another one has finished. |
|---|
| 50 | + */ |
|---|
| 51 | + struct mutex lock; |
|---|
| 46 | 52 | }; |
|---|
| 47 | 53 | |
|---|
| 48 | 54 | #define MX25_CQG_CHAN(chan, id) {\ |
|---|
| .. | .. |
|---|
| 140 | 146 | |
|---|
| 141 | 147 | switch (mask) { |
|---|
| 142 | 148 | case IIO_CHAN_INFO_RAW: |
|---|
| 143 | | - mutex_lock(&indio_dev->mlock); |
|---|
| 149 | + mutex_lock(&priv->lock); |
|---|
| 144 | 150 | ret = mx25_gcq_get_raw_value(&indio_dev->dev, chan, priv, val); |
|---|
| 145 | | - mutex_unlock(&indio_dev->mlock); |
|---|
| 151 | + mutex_unlock(&priv->lock); |
|---|
| 146 | 152 | return ret; |
|---|
| 147 | 153 | |
|---|
| 148 | 154 | case IIO_CHAN_INFO_SCALE: |
|---|
| .. | .. |
|---|
| 297 | 303 | struct mx25_gcq_priv *priv; |
|---|
| 298 | 304 | struct mx25_tsadc *tsadc = dev_get_drvdata(pdev->dev.parent); |
|---|
| 299 | 305 | struct device *dev = &pdev->dev; |
|---|
| 300 | | - struct resource *res; |
|---|
| 301 | 306 | void __iomem *mem; |
|---|
| 302 | 307 | int ret; |
|---|
| 303 | 308 | int i; |
|---|
| .. | .. |
|---|
| 308 | 313 | |
|---|
| 309 | 314 | priv = iio_priv(indio_dev); |
|---|
| 310 | 315 | |
|---|
| 311 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 312 | | - mem = devm_ioremap_resource(dev, res); |
|---|
| 316 | + mem = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 313 | 317 | if (IS_ERR(mem)) |
|---|
| 314 | 318 | return PTR_ERR(mem); |
|---|
| 315 | 319 | |
|---|
| .. | .. |
|---|
| 318 | 322 | dev_err(dev, "Failed to initialize regmap\n"); |
|---|
| 319 | 323 | return PTR_ERR(priv->regs); |
|---|
| 320 | 324 | } |
|---|
| 325 | + |
|---|
| 326 | + mutex_init(&priv->lock); |
|---|
| 321 | 327 | |
|---|
| 322 | 328 | init_completion(&priv->completed); |
|---|
| 323 | 329 | |
|---|
| .. | .. |
|---|
| 343 | 349 | |
|---|
| 344 | 350 | priv->irq = platform_get_irq(pdev, 0); |
|---|
| 345 | 351 | if (priv->irq <= 0) { |
|---|
| 346 | | - dev_err(dev, "Failed to get IRQ\n"); |
|---|
| 347 | 352 | ret = priv->irq; |
|---|
| 348 | 353 | if (!ret) |
|---|
| 349 | 354 | ret = -ENXIO; |
|---|
| .. | .. |
|---|
| 356 | 361 | goto err_clk_unprepare; |
|---|
| 357 | 362 | } |
|---|
| 358 | 363 | |
|---|
| 359 | | - indio_dev->dev.parent = &pdev->dev; |
|---|
| 360 | 364 | indio_dev->channels = mx25_gcq_channels; |
|---|
| 361 | 365 | indio_dev->num_channels = ARRAY_SIZE(mx25_gcq_channels); |
|---|
| 362 | 366 | indio_dev->info = &mx25_gcq_iio_info; |
|---|