diff options
| author | Donggeun Yoo <donggeunyoo.kernel@gmail.com> | 2026-09-02 00:21:26 +0900 |
|---|---|---|
| committer | Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> | 2026-09-07 02:24:53 +0100 |
| commit | e24328974a88aa8541e94e8bb8dfa2ade1b3c45d (patch) | |
| tree | 43a2533acc955d11f5cb8be1ecba0ab8ba4cbb1e /drivers/mtd/maps/plat-ram.c | |
| download | linux-stable-e24328974a88aa8541e94e8bb8dfa2ade1b3c45d.tar.gz linux-stable-e24328974a88aa8541e94e8bb8dfa2ade1b3c45d.zip | |
iio: proximity: vl53l0x-i2c: claim direct mode for raw readsgrafted
vl53l0x_read_raw() starts a single-shot ranging measurement and reads
back the result. Once the triggered buffer is enabled the sensor runs in
continuous mode and its data-ready interrupt is routed to the trigger,
so a concurrent in_distance_raw read disturbs the streaming setup and
never gets its completion, returning -ETIMEDOUT.
The original submission claimed direct mode here, but it was dropped
during review because the driver had no buffer support at the time [1].
Continuous (buffered) mode was later added without restoring the
claim [2], reintroducing the conflict.
Reject direct reads while buffered capture is active by claiming direct
mode around the measurement, as the vl53l1x sibling already does.
Fixes: 762186c6e7b1 ("iio: proximity: vl53l0x-i2c: Added continuous mode support")
Link: https://lore.kernel.org/linux-iio/20180911160300.GA9212@himanshu-Vostro-3559/ [1]
Link: https://lore.kernel.org/linux-iio/20240909101508.263085-3-abhashkumarjha123@gmail.com/ [2]
Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Diffstat (limited to 'drivers/mtd/maps/plat-ram.c')
| -rw-r--r-- | drivers/mtd/maps/plat-ram.c | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c new file mode 100644 index 000000000..816111031 --- /dev/null +++ b/drivers/mtd/maps/plat-ram.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* drivers/mtd/maps/plat-ram.c + * + * (c) 2004-2005 Simtec Electronics + * http://www.simtec.co.uk/products/SWLINUX/ + * Ben Dooks <ben@simtec.co.uk> + * + * Generic platform device based RAM map +*/ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/slab.h> +#include <linux/platform_device.h> + +#include <linux/mtd/mtd.h> +#include <linux/mtd/map.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/plat-ram.h> + +#include <asm/io.h> + +/* private structure for each mtd platform ram device created */ + +struct platram_info { + struct device *dev; + struct mtd_info *mtd; + struct map_info map; + struct platdata_mtd_ram *pdata; +}; + +/* to_platram_info() + * + * device private data to struct platram_info conversion +*/ + +static inline struct platram_info *to_platram_info(struct platform_device *dev) +{ + return platform_get_drvdata(dev); +} + +/* platram_setrw + * + * call the platform device's set rw/ro control + * + * to = 0 => read-only + * = 1 => read-write +*/ + +static inline void platram_setrw(struct platram_info *info, int to) +{ + if (info->pdata == NULL) + return; + + if (info->pdata->set_rw != NULL) + (info->pdata->set_rw)(info->dev, to); +} + +/* platram_remove + * + * called to remove the device from the driver's control +*/ + +static void platram_remove(struct platform_device *pdev) +{ + struct platram_info *info = to_platram_info(pdev); + + dev_dbg(&pdev->dev, "removing device\n"); + + if (info == NULL) + return; + + if (info->mtd) { + mtd_device_unregister(info->mtd); + map_destroy(info->mtd); + } + + /* ensure ram is left read-only */ + + platram_setrw(info, PLATRAM_RO); + + kfree(info); +} + +/* platram_probe + * + * called from device drive system when a device matching our + * driver is found. +*/ + +static int platram_probe(struct platform_device *pdev) +{ + struct platdata_mtd_ram *pdata; + struct platram_info *info; + struct resource *res; + int err = 0; + + dev_dbg(&pdev->dev, "probe entered\n"); + + if (dev_get_platdata(&pdev->dev) == NULL) { + dev_err(&pdev->dev, "no platform data supplied\n"); + err = -ENOENT; + goto exit_error; + } + + pdata = dev_get_platdata(&pdev->dev); + + info = kzalloc_obj(*info); + if (info == NULL) { + err = -ENOMEM; + goto exit_error; + } + + platform_set_drvdata(pdev, info); + + info->dev = &pdev->dev; + info->pdata = pdata; + + /* get the resource for the memory mapping */ + info->map.virt = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(info->map.virt)) { + err = PTR_ERR(info->map.virt); + goto exit_free; + } + + dev_dbg(&pdev->dev, "got platform resource %p (0x%llx)\n", res, + (unsigned long long)res->start); + + /* setup map parameters */ + + info->map.phys = res->start; + info->map.size = resource_size(res); + info->map.name = pdata->mapname != NULL ? + (char *)pdata->mapname : (char *)pdev->name; + info->map.bankwidth = pdata->bankwidth; + + dev_dbg(&pdev->dev, "virt %p, %lu bytes\n", info->map.virt, info->map.size); + + simple_map_init(&info->map); + + dev_dbg(&pdev->dev, "initialised map, probing for mtd\n"); + + /* probe for the right mtd map driver + * supplied by the platform_data struct */ + + if (pdata->map_probes) { + const char * const *map_probes = pdata->map_probes; + + for ( ; !info->mtd && *map_probes; map_probes++) + info->mtd = do_map_probe(*map_probes , &info->map); + } + /* fallback to map_ram */ + else + info->mtd = do_map_probe("map_ram", &info->map); + + if (info->mtd == NULL) { + dev_err(&pdev->dev, "failed to probe for map_ram\n"); + err = -ENOMEM; + goto exit_free; + } + + info->mtd->dev.parent = &pdev->dev; + + platram_setrw(info, PLATRAM_RW); + + /* check to see if there are any available partitions, or whether + * to add this device whole */ + + err = mtd_device_parse_register(info->mtd, pdata->probes, NULL, + pdata->partitions, + pdata->nr_partitions); + if (err) { + dev_err(&pdev->dev, "failed to register mtd device\n"); + goto exit_free; + } + + dev_info(&pdev->dev, "registered mtd device\n"); + + if (pdata->nr_partitions) { + /* add the whole device. */ + err = mtd_device_register(info->mtd, NULL, 0); + if (err) { + dev_err(&pdev->dev, + "failed to register the entire device\n"); + goto exit_free; + } + } + + return 0; + + exit_free: + platram_remove(pdev); + exit_error: + return err; +} + +/* device driver info */ + +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:mtd-ram"); + +static struct platform_driver platram_driver = { + .probe = platram_probe, + .remove = platram_remove, + .driver = { + .name = "mtd-ram", + }, +}; + +module_platform_driver(platram_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_DESCRIPTION("MTD platform RAM map driver"); |
