diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
commit | 62b8c978ee6b8d135d9e7953221de58000dba986 (patch) | |
tree | 683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/base/regmap | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz |
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r-- | drivers/base/regmap/Kconfig | 5 | ||||
-rw-r--r-- | drivers/base/regmap/Makefile | 1 | ||||
-rw-r--r-- | drivers/base/regmap/internal.h | 8 | ||||
-rw-r--r-- | drivers/base/regmap/regcache.c | 19 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 57 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-irq.c | 16 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-spi.c | 3 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-spmi.c | 90 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 366 |
9 files changed, 58 insertions, 507 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 4251570..f0d3054 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -3,7 +3,7 @@ # subsystems should select the appropriate symbols. config REGMAP - default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_MMIO || REGMAP_IRQ) + default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ) select LZO_COMPRESS select LZO_DECOMPRESS select IRQ_DOMAIN if REGMAP_IRQ @@ -15,9 +15,6 @@ config REGMAP_I2C config REGMAP_SPI tristate -config REGMAP_SPMI - tristate - config REGMAP_MMIO tristate diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index a7c670b..cf12998 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile @@ -3,6 +3,5 @@ obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o -obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 33414b1..57f7778 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -44,6 +44,7 @@ struct regmap_format { struct regmap_async { struct list_head list; + struct work_struct cleanup; struct regmap *map; void *work_buf; }; @@ -63,11 +64,9 @@ struct regmap { void *bus_context; const char *name; - bool async; spinlock_t async_lock; wait_queue_head_t async_waitq; struct list_head async_list; - struct list_head async_free; int async_ret; #ifdef CONFIG_DEBUG_FS @@ -180,9 +179,6 @@ struct regmap_field { /* lsb */ unsigned int shift; unsigned int reg; - - unsigned int id_size; - unsigned int id_offset; }; #ifdef CONFIG_DEBUG_FS @@ -222,7 +218,7 @@ bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, int regcache_lookup_reg(struct regmap *map, unsigned int reg); int _regmap_raw_write(struct regmap *map, unsigned int reg, - const void *val, size_t val_len); + const void *val, size_t val_len, bool async); void regmap_async_complete_cb(struct regmap_async *async, int ret); diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index d4dd771..d6c2d69 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -307,8 +307,6 @@ int regcache_sync(struct regmap *map) if (!map->cache_dirty) goto out; - map->async = true; - /* Apply any patch first */ map->cache_bypass = 1; for (i = 0; i < map->patch_regs; i++) { @@ -334,15 +332,11 @@ int regcache_sync(struct regmap *map) map->cache_dirty = false; out: + trace_regcache_sync(map->dev, name, "stop"); /* Restore the bypass state */ - map->async = false; map->cache_bypass = bypass; map->unlock(map->lock_arg); - regmap_async_complete(map); - - trace_regcache_sync(map->dev, name, "stop"); - return ret; } EXPORT_SYMBOL_GPL(regcache_sync); @@ -381,23 +375,17 @@ int regcache_sync_region(struct regmap *map, unsigned int min, if (!map->cache_dirty) goto out; - map->async = true; - if (map->cache_ops->sync) ret = map->cache_ops->sync(map, min, max); else ret = regcache_default_sync(map, min, max); out: + trace_regcache_sync(map->dev, name, "stop region"); /* Restore the bypass state */ map->cache_bypass = bypass; - map->async = false; map->unlock(map->lock_arg); - regmap_async_complete(map); - - trace_regcache_sync(map->dev, name, "stop region"); - return ret; } EXPORT_SYMBOL_GPL(regcache_sync_region); @@ -643,7 +631,8 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data, map->cache_bypass = 1; - ret = _regmap_raw_write(map, base, *data, count * val_bytes); + ret = _regmap_raw_write(map, base, *data, count * val_bytes, + false); map->cache_bypass = 0; diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index c5471cd..de11eca 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -15,19 +15,10 @@ #include <linux/debugfs.h> #include <linux/uaccess.h> #include <linux/device.h> -#include <linux/list.h> #include "internal.h" -struct regmap_debugfs_node { - struct regmap *map; - const char *name; - struct list_head link; -}; - static struct dentry *regmap_debugfs_root; -static LIST_HEAD(regmap_debugfs_early_list); -static DEFINE_MUTEX(regmap_debugfs_early_lock); /* Calculate the length of a fixed format */ static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size) @@ -474,20 +465,6 @@ void regmap_debugfs_init(struct regmap *map, const char *name) struct rb_node *next; struct regmap_range_node *range_node; - /* If we don't have the debugfs root yet, postpone init */ - if (!regmap_debugfs_root) { - struct regmap_debugfs_node *node; - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) - return; - node->map = map; - node->name = name; - mutex_lock(®map_debugfs_early_lock); - list_add(&node->link, ®map_debugfs_early_list); - mutex_unlock(®map_debugfs_early_lock); - return; - } - INIT_LIST_HEAD(&map->debugfs_off_cache); mutex_init(&map->cache_lock); @@ -542,42 +519,18 @@ void regmap_debugfs_init(struct regmap *map, const char *name) void regmap_debugfs_exit(struct regmap *map) { - if (map->debugfs) { - debugfs_remove_recursive(map->debugfs); - mutex_lock(&map->cache_lock); - regmap_debugfs_free_dump_cache(map); - mutex_unlock(&map->cache_lock); - kfree(map->debugfs_name); - } else { - struct regmap_debugfs_node *node, *tmp; - - mutex_lock(®map_debugfs_early_lock); - list_for_each_entry_safe(node, tmp, ®map_debugfs_early_list, - link) { - if (node->map == map) { - list_del(&node->link); - kfree(node); - } - } - mutex_unlock(®map_debugfs_early_lock); - } + debugfs_remove_recursive(map->debugfs); + mutex_lock(&map->cache_lock); + regmap_debugfs_free_dump_cache(map); + mutex_unlock(&map->cache_lock); + kfree(map->debugfs_name); } void regmap_debugfs_initcall(void) { - struct regmap_debugfs_node *node, *tmp; - regmap_debugfs_root = debugfs_create_dir("regmap", NULL); if (!regmap_debugfs_root) { pr_warn("regmap: Failed to create debugfs root\n"); return; } - - mutex_lock(®map_debugfs_early_lock); - list_for_each_entry_safe(node, tmp, ®map_debugfs_early_list, link) { - regmap_debugfs_init(node->map, node->name); - list_del(&node->link); - kfree(node); - } - mutex_unlock(®map_debugfs_early_lock); } diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 763c60d..d10456f 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -105,22 +105,6 @@ static void regmap_irq_sync_unlock(struct irq_data *data) "Failed to sync wakes in %x: %d\n", reg, ret); } - - if (!d->chip->init_ack_masked) - continue; - /* - * Ack all the masked interrupts uncondictionly, - * OR if there is masked interrupt which hasn't been Acked, - * it'll be ignored in irq handler, then may introduce irq storm - */ - if (d->mask_buf[i] && d->chip->ack_base) { - reg = d->chip->ack_base + - (i * map->reg_stride * d->irq_reg_stride); - ret = regmap_write(map, reg, d->mask_buf[i]); - if (ret != 0) - dev_err(d->map->dev, "Failed to ack 0x%x: %d\n", - reg, ret); - } } if (d->chip->runtime_pm) diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c index 37f12ae..4c506bd 100644 --- a/drivers/base/regmap/regmap-spi.c +++ b/drivers/base/regmap/regmap-spi.c @@ -73,8 +73,7 @@ static int regmap_spi_async_write(void *context, spi_message_init(&async->m); spi_message_add_tail(&async->t[0], &async->m); - if (val) - spi_message_add_tail(&async->t[1], &async->m); + spi_message_add_tail(&async->t[1], &async->m); async->m.complete = regmap_spi_complete; async->m.context = async; diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c deleted file mode 100644 index ac23910..0000000 --- a/drivers/base/regmap/regmap-spmi.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Register map access API - SPMI support - * - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Based on regmap-i2c.c: - * Copyright 2011 Wolfson Microelectronics plc - * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#include <linux/regmap.h> -#include <linux/spmi.h> -#include <linux/module.h> -#include <linux/init.h> - -static int regmap_spmi_read(void *context, - const void *reg, size_t reg_size, - void *val, size_t val_size) -{ - BUG_ON(reg_size != 2); - return spmi_ext_register_readl(context, *(u16 *)reg, - val, val_size); -} - -static int regmap_spmi_gather_write(void *context, - const void *reg, size_t reg_size, - const void *val, size_t val_size) -{ - BUG_ON(reg_size != 2); - return spmi_ext_register_writel(context, *(u16 *)reg, val, val_size); -} - -static int regmap_spmi_write(void *context, const void *data, - size_t count) -{ - BUG_ON(count < 2); - return regmap_spmi_gather_write(context, data, 2, data + 2, count - 2); -} - -static struct regmap_bus regmap_spmi = { - .read = regmap_spmi_read, - .write = regmap_spmi_write, - .gather_write = regmap_spmi_gather_write, - .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, - .val_format_endian_default = REGMAP_ENDIAN_NATIVE, -}; - -/** - * regmap_init_spmi(): Initialize register map - * - * @sdev: Device that will be interacted with - * @config: Configuration for register map - * - * The return value will be an ERR_PTR() on error or a valid pointer to - * a struct regmap. - */ -struct regmap *regmap_init_spmi(struct spmi_device *sdev, - const struct regmap_config *config) -{ - return regmap_init(&sdev->dev, ®map_spmi, sdev, config); -} -EXPORT_SYMBOL_GPL(regmap_init_spmi); - -/** - * devm_regmap_init_spmi(): Initialise managed register map - * - * @sdev: Device that will be interacted with - * @config: Configuration for register map - * - * The return value will be an ERR_PTR() on error or a valid pointer - * to a struct regmap. The regmap will be automatically freed by the - * device management code. - */ -struct regmap *devm_regmap_init_spmi(struct spmi_device *sdev, - const struct regmap_config *config) -{ - return devm_regmap_init(&sdev->dev, ®map_spmi, sdev, config); -} -EXPORT_SYMBOL_GPL(devm_regmap_init_spmi); - -MODULE_LICENSE("GPL"); diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 9c021d9..7d689a1 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -42,6 +42,15 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, static int _regmap_bus_raw_write(void *context, unsigned int reg, unsigned int val); +static void async_cleanup(struct work_struct *work) +{ + struct regmap_async *async = container_of(work, struct regmap_async, + cleanup); + + kfree(async->work_buf); + kfree(async); +} + bool regmap_reg_in_ranges(unsigned int reg, const struct regmap_range *ranges, unsigned int nranges) @@ -456,7 +465,6 @@ struct regmap *regmap_init(struct device *dev, spin_lock_init(&map->async_lock); INIT_LIST_HEAD(&map->async_list); - INIT_LIST_HEAD(&map->async_free); init_waitqueue_head(&map->async_waitq); if (config->read_flag_mask || config->write_flag_mask) { @@ -813,8 +821,6 @@ static void regmap_field_init(struct regmap_field *rm_field, rm_field->reg = reg_field.reg; rm_field->shift = reg_field.lsb; rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb); - rm_field->id_size = reg_field.id_size; - rm_field->id_offset = reg_field.id_offset; } /** @@ -936,22 +942,12 @@ EXPORT_SYMBOL_GPL(regmap_reinit_cache); */ void regmap_exit(struct regmap *map) { - struct regmap_async *async; - regcache_exit(map); regmap_debugfs_exit(map); regmap_range_exit(map); if (map->bus && map->bus->free_context) map->bus->free_context(map->bus_context); kfree(map->work_buf); - while (!list_empty(&map->async_free)) { - async = list_first_entry_or_null(&map->async_free, - struct regmap_async, - list); - list_del(&async->list); - kfree(async->work_buf); - kfree(async); - } kfree(map); } EXPORT_SYMBOL_GPL(regmap_exit); @@ -1043,7 +1039,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg, } int _regmap_raw_write(struct regmap *map, unsigned int reg, - const void *val, size_t val_len) + const void *val, size_t val_len, bool async) { struct regmap_range_node *range; unsigned long flags; @@ -1095,7 +1091,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, dev_dbg(map->dev, "Writing window %d/%zu\n", win_residue, val_len / map->format.val_bytes); ret = _regmap_raw_write(map, reg, val, win_residue * - map->format.val_bytes); + map->format.val_bytes, async); if (ret != 0) return ret; @@ -1118,72 +1114,49 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, u8[0] |= map->write_flag_mask; - /* - * Essentially all I/O mechanisms will be faster with a single - * buffer to write. Since register syncs often generate raw - * writes of single registers optimise that case. - */ - if (val != work_val && val_len == map->format.val_bytes) { - memcpy(work_val, val, map->format.val_bytes); - val = work_val; - } - - if (map->async && map->bus->async_write) { - struct regmap_async *async; + if (async && map->bus->async_write) { + struct regmap_async *async = map->bus->async_alloc(); + if (!async) + return -ENOMEM; trace_regmap_async_write_start(map->dev, reg, val_len); - spin_lock_irqsave(&map->async_lock, flags); - async = list_first_entry_or_null(&map->async_free, - struct regmap_async, - list); - if (async) - list_del(&async->list); - spin_unlock_irqrestore(&map->async_lock, flags); - - if (!async) { - async = map->bus->async_alloc(); - if (!async) - return -ENOMEM; - - async->work_buf = kzalloc(map->format.buf_size, - GFP_KERNEL | GFP_DMA); - if (!async->work_buf) { - kfree(async); - return -ENOMEM; - } + async->work_buf = kzalloc(map->format.buf_size, + GFP_KERNEL | GFP_DMA); + if (!async->work_buf) { + kfree(async); + return -ENOMEM; } + INIT_WORK(&async->cleanup, async_cleanup); async->map = map; /* If the caller supplied the value we can use it safely. */ memcpy(async->work_buf, map->work_buf, map->format.pad_bytes + map->format.reg_bytes + map->format.val_bytes); + if (val == work_val) + val = async->work_buf + map->format.pad_bytes + + map->format.reg_bytes; spin_lock_irqsave(&map->async_lock, flags); list_add_tail(&async->list, &map->async_list); spin_unlock_irqrestore(&map->async_lock, flags); - if (val != work_val) - ret = map->bus->async_write(map->bus_context, - async->work_buf, - map->format.reg_bytes + - map->format.pad_bytes, - val, val_len, async); - else - ret = map->bus->async_write(map->bus_context, - async->work_buf, - map->format.reg_bytes + - map->format.pad_bytes + - val_len, NULL, 0, async); + ret = map->bus->async_write(map->bus_context, async->work_buf, + map->format.reg_bytes + + map->format.pad_bytes, + val, val_len, async); if (ret != 0) { dev_err(map->dev, "Failed to schedule write: %d\n", ret); spin_lock_irqsave(&map->async_lock, flags); - list_move(&async->list, &map->async_free); + list_del(&async->list); spin_unlock_irqrestore(&map->async_lock, flags); + + kfree(async->work_buf); + kfree(async); } return ret; @@ -1280,7 +1253,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, map->work_buf + map->format.reg_bytes + map->format.pad_bytes, - map->format.val_bytes); + map->format.val_bytes, false); } static inline void *_regmap_map_get_context(struct regmap *map) @@ -1345,37 +1318,6 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) EXPORT_SYMBOL_GPL(regmap_write); /** - * regmap_write_async(): Write a value to a single register asynchronously - * - * @map: Register map to write to - * @reg: Register to write to - * @val: Value to be written - * - * A value of zero will be returned on success, a negative errno will - * be returned in error cases. - */ -int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val) -{ - int ret; - - if (reg % map->reg_stride) - return -EINVAL; - - map->lock(map->lock_arg); - - map->async = true; - - ret = _regmap_write(map, reg, val); - - map->async = false; - - map->unlock(map->lock_arg); - - return ret; -} -EXPORT_SYMBOL_GPL(regmap_write_async); - -/** * regmap_raw_write(): Write raw values to one or more registers * * @map: Register map to write to @@ -1403,7 +1345,7 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, map->lock(map->lock_arg); - ret = _regmap_raw_write(map, reg, val, val_len); + ret = _regmap_raw_write(map, reg, val, val_len, false); map->unlock(map->lock_arg); @@ -1427,74 +1369,6 @@ int regmap_field_write(struct regmap_field *field, unsigned int val) } EXPORT_SYMBOL_GPL(regmap_field_write); -/** - * regmap_field_update_bits(): Perform a read/modify/write cycle - * on the register field - * - * @field: Register field to write to - * @mask: Bitmask to change - * @val: Value to be written - * - * A value of zero will be returned on success, a negative errno will - * be returned in error cases. - */ -int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val) -{ - mask = (mask << field->shift) & field->mask; - - return regmap_update_bits(field->regmap, field->reg, - mask, val << field->shift); -} -EXPORT_SYMBOL_GPL(regmap_field_update_bits); - -/** - * regmap_fields_write(): Write a value to a single register field with port ID - * - * @field: Register field to write to - * @id: port ID - * @val: Value to be written - * - * A value of zero will be returned on success, a negative errno will - * be returned in error cases. - */ -int regmap_fields_write(struct regmap_field *field, unsigned int id, - unsigned int val) -{ - if (id >= field->id_size) - return -EINVAL; - - return regmap_update_bits(field->regmap, - field->reg + (field->id_offset * id), - field->mask, val << field->shift); -} -EXPORT_SYMBOL_GPL(regmap_fields_write); - -/** - * regmap_fields_update_bits(): Perform a read/modify/write cycle - * on the register field - * - * @field: Register field to write to - * @id: port ID - * @mask: Bitmask to change - * @val: Value to be written - * - * A value of zero will be returned on success, a negative errno will - * be returned in error cases. - */ -int regmap_fields_update_bits(struct regmap_field *field, unsigned int id, - unsigned int mask, unsigned int val) -{ - if (id >= field->id_size) - return -EINVAL; - - mask = (mask << field->shift) & field->mask; - - return regmap_update_bits(field->regmap, - field->reg + (field->id_offset * id), - mask, val << field->shift); -} -EXPORT_SYMBOL_GPL(regmap_fields_update_bits); - /* * regmap_bulk_write(): Write multiple registers to the device * @@ -1544,15 +1418,16 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, */ if (map->use_single_rw) { for (i = 0; i < val_count; i++) { - ret = _regmap_raw_write(map, - reg + (i * map->reg_stride), - val + (i * val_bytes), - val_bytes); + ret = regmap_raw_write(map, + reg + (i * map->reg_stride), + val + (i * val_bytes), + val_bytes); if (ret != 0) return ret; } } else { - ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); + ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count, + false); } if (val_bytes != 1) @@ -1564,47 +1439,6 @@ out: } EXPORT_SYMBOL_GPL(regmap_bulk_write); -/* - * regmap_multi_reg_write(): Write multiple registers to the device - * - * where the set of register are supplied in any order - * - * @map: Register map to write to - * @regs: Array of structures containing register,value to be written - * @num_regs: Number of registers to write - * - * This function is intended to be used for writing a large block of data - * atomically to the device in single transfer for those I2C client devices - * that implement this alternative block write mode. - * - * A value of zero will be returned on success, a negative errno will - * be returned in error cases. - */ -int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs, - int num_regs) -{ - int ret = 0, i; - - for (i = 0; i < num_regs; i++) { - int reg = regs[i].reg; - if (reg % map->reg_stride) - return -EINVAL; - } - - map->lock(map->lock_arg); - - for (i = 0; i < num_regs; i++) { - ret = _regmap_write(map, regs[i].reg, regs[i].def); - if (ret != 0) - goto out; - } -out: - map->unlock(map->lock_arg); - - return ret; -} -EXPORT_SYMBOL_GPL(regmap_multi_reg_write); - /** * regmap_raw_write_async(): Write raw values to one or more registers * asynchronously @@ -1639,11 +1473,7 @@ int regmap_raw_write_async(struct regmap *map, unsigned int reg, map->lock(map->lock_arg); - map->async = true; - - ret = _regmap_raw_write(map, reg, val, val_len); - - map->async = false; + ret = _regmap_raw_write(map, reg, val, val_len, true); map->unlock(map->lock_arg); @@ -1847,39 +1677,6 @@ int regmap_field_read(struct regmap_field *field, unsigned int *val) EXPORT_SYMBOL_GPL(regmap_field_read); /** - * regmap_fields_read(): Read a value to a single register field with port ID - * - * @field: Register field to read from - * @id: port ID - * @val: Pointer to store read value - * - * A value of zero will be returned on success, a negative errno will - * be returned in error cases. - */ -int regmap_fields_read(struct regmap_field *field, unsigned int id, - unsigned int *val) -{ - int ret; - unsigned int reg_val; - - if (id >= field->id_size) - return -EINVAL; - - ret = regmap_read(field->regmap, - field->reg + (field->id_offset * id), - ®_val); - if (ret != 0) - return ret; - - reg_val &= field->mask; - reg_val >>= field->shift; - *val = reg_val; - - return ret; -} -EXPORT_SYMBOL_GPL(regmap_fields_read); - -/** * regmap_bulk_read(): Read multiple registers from the device * * @map: Register map to write to @@ -1991,41 +1788,6 @@ int regmap_update_bits(struct regmap *map, unsigned int reg, EXPORT_SYMBOL_GPL(regmap_update_bits); /** - * regmap_update_bits_async: Perform a read/modify/write cycle on the register - * map asynchronously - * - * @map: Register map to update - * @reg: Register to update - * @mask: Bitmask to change - * @val: New value for bitmask - * - * With most buses the read must be done synchronously so this is most - * useful for devices with a cache which do not need to interact with - * the hardware to determine the current register value. - * - * Returns zero for success, a negative number on error. - */ -int regmap_update_bits_async(struct regmap *map, unsigned int reg, - unsigned int mask, unsigned int val) -{ - bool change; - int ret; - - map->lock(map->lock_arg); - - map->async = true; - - ret = _regmap_update_bits(map, reg, mask, val, &change); - - map->async = false; - - map->unlock(map->lock_arg); - - return ret; -} -EXPORT_SYMBOL_GPL(regmap_update_bits_async); - -/** * regmap_update_bits_check: Perform a read/modify/write cycle on the * register map and report if updated * @@ -2050,43 +1812,6 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg, } EXPORT_SYMBOL_GPL(regmap_update_bits_check); -/** - * regmap_update_bits_check_async: Perform a read/modify/write cycle on the - * register map asynchronously and report if - * updated - * - * @map: Register map to update - * @reg: Register to update - * @mask: Bitmask to change - * @val: New value for bitmask - * @change: Boolean indicating if a write was done - * - * With most buses the read must be done synchronously so this is most - * useful for devices with a cache which do not need to interact with - * the hardware to determine the current register value. - * - * Returns zero for success, a negative number on error. - */ -int regmap_update_bits_check_async(struct regmap *map, unsigned int reg, - unsigned int mask, unsigned int val, - bool *change) -{ - int ret; - - map->lock(map->lock_arg); - - map->async = true; - - ret = _regmap_update_bits(map, reg, mask, val, change); - - map->async = false; - - map->unlock(map->lock_arg); - - return ret; -} -EXPORT_SYMBOL_GPL(regmap_update_bits_check_async); - void regmap_async_complete_cb(struct regmap_async *async, int ret) { struct regmap *map = async->map; @@ -2095,7 +1820,8 @@ void regmap_async_complete_cb(struct regmap_async *async, int ret) trace_regmap_async_io_complete(map->dev); spin_lock(&map->async_lock); - list_move(&async->list, &map->async_free); + + list_del(&async->list); wake = list_empty(&map->async_list); if (ret != 0) @@ -2103,6 +1829,8 @@ void regmap_async_complete_cb(struct regmap_async *async, int ret) spin_unlock(&map->async_lock); + schedule_work(&async->cleanup); + if (wake) wake_up(&map->async_waitq); } @@ -2178,7 +1906,6 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, bypass = map->cache_bypass; map->cache_bypass = true; - map->async = true; /* Write out first; it's useful to apply even if we fail later. */ for (i = 0; i < num_regs; i++) { @@ -2202,13 +1929,10 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, } out: - map->async = false; map->cache_bypass = bypass; map->unlock(map->lock_arg); - regmap_async_complete(map); - return ret; } EXPORT_SYMBOL_GPL(regmap_register_patch); |