diff --git a/[refs] b/[refs] index e8cb928344fe..c7086b556257 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5dea215028686a67e815c32a54dc89fb3467ab05 +refs/heads/master: 878ec67b3ac528a2b6d44055f049cdbb9cfda30c diff --git a/trunk/drivers/base/regmap/Makefile b/trunk/drivers/base/regmap/Makefile index cf129980abd0..5e75d1b683e2 100644 --- a/trunk/drivers/base/regmap/Makefile +++ b/trunk/drivers/base/regmap/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_REGMAP) += regmap.o regcache.o -obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o +obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o diff --git a/trunk/drivers/base/regmap/internal.h b/trunk/drivers/base/regmap/internal.h index 70ca270b77e2..401d1919635a 100644 --- a/trunk/drivers/base/regmap/internal.h +++ b/trunk/drivers/base/regmap/internal.h @@ -16,7 +16,6 @@ #include #include #include -#include struct regmap; struct regcache_ops; @@ -26,7 +25,6 @@ struct regmap_debugfs_off_cache { off_t min; off_t max; unsigned int base_reg; - unsigned int max_reg; }; struct regmap_format { @@ -41,13 +39,6 @@ struct regmap_format { unsigned int (*parse_val)(void *buf); }; -struct regmap_async { - struct list_head list; - struct work_struct cleanup; - struct regmap *map; - void *work_buf; -}; - struct regmap { struct mutex mutex; spinlock_t spinlock; @@ -62,11 +53,6 @@ struct regmap { void *bus_context; const char *name; - spinlock_t async_lock; - wait_queue_head_t async_waitq; - struct list_head async_list; - int async_ret; - #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; const char *debugfs_name; @@ -88,9 +74,6 @@ struct regmap { const struct regmap_access_table *volatile_table; const struct regmap_access_table *precious_table; - int (*reg_read)(void *context, unsigned int reg, unsigned int *val); - int (*reg_write)(void *context, unsigned int reg, unsigned int val); - u8 read_flag_mask; u8 write_flag_mask; @@ -192,10 +175,7 @@ bool regcache_set_val(void *base, unsigned int idx, unsigned int val, unsigned int word_size); int regcache_lookup_reg(struct regmap *map, unsigned int reg); -void regmap_async_complete_cb(struct regmap_async *async, int ret); - extern struct regcache_ops regcache_rbtree_ops; extern struct regcache_ops regcache_lzo_ops; -extern struct regcache_ops regcache_flat_ops; #endif diff --git a/trunk/drivers/base/regmap/regcache-flat.c b/trunk/drivers/base/regmap/regcache-flat.c deleted file mode 100644 index d9762e41959b..000000000000 --- a/trunk/drivers/base/regmap/regcache-flat.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Register cache access API - flat caching support - * - * Copyright 2012 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "internal.h" - -static int regcache_flat_init(struct regmap *map) -{ - int i; - unsigned int *cache; - - map->cache = kzalloc(sizeof(unsigned int) * (map->max_register + 1), - GFP_KERNEL); - if (!map->cache) - return -ENOMEM; - - cache = map->cache; - - for (i = 0; i < map->num_reg_defaults; i++) - cache[map->reg_defaults[i].reg] = map->reg_defaults[i].def; - - return 0; -} - -static int regcache_flat_exit(struct regmap *map) -{ - kfree(map->cache); - map->cache = NULL; - - return 0; -} - -static int regcache_flat_read(struct regmap *map, - unsigned int reg, unsigned int *value) -{ - unsigned int *cache = map->cache; - - *value = cache[reg]; - - return 0; -} - -static int regcache_flat_write(struct regmap *map, unsigned int reg, - unsigned int value) -{ - unsigned int *cache = map->cache; - - cache[reg] = value; - - return 0; -} - -struct regcache_ops regcache_flat_ops = { - .type = REGCACHE_FLAT, - .name = "flat", - .init = regcache_flat_init, - .exit = regcache_flat_exit, - .read = regcache_flat_read, - .write = regcache_flat_write, -}; diff --git a/trunk/drivers/base/regmap/regcache.c b/trunk/drivers/base/regmap/regcache.c index e69ff3e4742c..835883bda977 100644 --- a/trunk/drivers/base/regmap/regcache.c +++ b/trunk/drivers/base/regmap/regcache.c @@ -22,7 +22,6 @@ static const struct regcache_ops *cache_types[] = { ®cache_rbtree_ops, ®cache_lzo_ops, - ®cache_flat_ops, }; static int regcache_hw_init(struct regmap *map) diff --git a/trunk/drivers/base/regmap/regmap-debugfs.c b/trunk/drivers/base/regmap/regmap-debugfs.c index 78d5f20c5f5b..d9a6c94ce423 100644 --- a/trunk/drivers/base/regmap/regmap-debugfs.c +++ b/trunk/drivers/base/regmap/regmap-debugfs.c @@ -81,8 +81,6 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, struct regmap_debugfs_off_cache *c = NULL; loff_t p = 0; unsigned int i, ret; - unsigned int fpos_offset; - unsigned int reg_offset; /* * If we don't have a cache build one so we don't have to do a @@ -95,9 +93,6 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, regmap_precious(map, i)) { if (c) { c->max = p - 1; - fpos_offset = c->max - c->min; - reg_offset = fpos_offset / map->debugfs_tot_len; - c->max_reg = c->base_reg + reg_offset; list_add_tail(&c->list, &map->debugfs_off_cache); c = NULL; @@ -124,9 +119,6 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, /* Close the last entry off if we didn't scan beyond it */ if (c) { c->max = p - 1; - fpos_offset = c->max - c->min; - reg_offset = fpos_offset / map->debugfs_tot_len; - c->max_reg = c->base_reg + reg_offset; list_add_tail(&c->list, &map->debugfs_off_cache); } @@ -136,38 +128,25 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, * allocate and we should never be in this code if there are * no registers at all. */ - WARN_ON(list_empty(&map->debugfs_off_cache)); - ret = base; + if (list_empty(&map->debugfs_off_cache)) { + WARN_ON(list_empty(&map->debugfs_off_cache)); + return base; + } - /* Find the relevant block:offset */ + /* Find the relevant block */ list_for_each_entry(c, &map->debugfs_off_cache, list) { if (from >= c->min && from <= c->max) { - fpos_offset = from - c->min; - reg_offset = fpos_offset / map->debugfs_tot_len; - *pos = c->min + (reg_offset * map->debugfs_tot_len); - return c->base_reg + reg_offset; + *pos = c->min; + return c->base_reg; } - *pos = c->max; - ret = c->max_reg; + *pos = c->min; + ret = c->base_reg; } return ret; } -static inline void regmap_calc_tot_len(struct regmap *map, - void *buf, size_t count) -{ - /* Calculate the length of a fixed format */ - if (!map->debugfs_tot_len) { - map->debugfs_reg_len = regmap_calc_reg_len(map->max_register, - buf, count); - map->debugfs_val_len = 2 * map->format.val_bytes; - map->debugfs_tot_len = map->debugfs_reg_len + - map->debugfs_val_len + 3; /* : \n */ - } -} - static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, unsigned int to, char __user *user_buf, size_t count, loff_t *ppos) @@ -186,7 +165,14 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, if (!buf) return -ENOMEM; - regmap_calc_tot_len(map, buf, count); + /* Calculate the length of a fixed format */ + if (!map->debugfs_tot_len) { + map->debugfs_reg_len = regmap_calc_reg_len(map->max_register, + buf, count); + map->debugfs_val_len = 2 * map->format.val_bytes; + map->debugfs_tot_len = map->debugfs_reg_len + + map->debugfs_val_len + 3; /* : \n */ + } /* Work out which register we're starting at */ start_reg = regmap_debugfs_get_dump_start(map, from, *ppos, &p); @@ -201,7 +187,7 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, /* If we're in the region the user is trying to read */ if (p >= *ppos) { /* ...but not beyond it */ - if (buf_pos + map->debugfs_tot_len > count) + if (buf_pos + 1 + map->debugfs_tot_len >= count) break; /* Format the register */ diff --git a/trunk/drivers/base/regmap/regmap-irq.c b/trunk/drivers/base/regmap/regmap-irq.c index 4706c63d0bc6..5972ad958544 100644 --- a/trunk/drivers/base/regmap/regmap-irq.c +++ b/trunk/drivers/base/regmap/regmap-irq.c @@ -34,7 +34,6 @@ struct regmap_irq_chip_data { int irq; int wake_count; - void *status_reg_buf; unsigned int *status_buf; unsigned int *mask_buf; unsigned int *mask_buf_def; @@ -88,23 +87,6 @@ static void regmap_irq_sync_unlock(struct irq_data *data) if (ret != 0) dev_err(d->map->dev, "Failed to sync masks in %x\n", reg); - - reg = d->chip->wake_base + - (i * map->reg_stride * d->irq_reg_stride); - if (d->wake_buf) { - if (d->chip->wake_invert) - ret = regmap_update_bits(d->map, reg, - d->mask_buf_def[i], - ~d->wake_buf[i]); - else - ret = regmap_update_bits(d->map, reg, - d->mask_buf_def[i], - d->wake_buf[i]); - if (ret != 0) - dev_err(d->map->dev, - "Failed to sync wakes in %x: %d\n", - reg, ret); - } } if (d->chip->runtime_pm) @@ -147,15 +129,16 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on) struct regmap *map = d->map; const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); + if (!d->chip->wake_base) + return -EINVAL; + if (on) { - if (d->wake_buf) - d->wake_buf[irq_data->reg_offset / map->reg_stride] - &= ~irq_data->mask; + d->wake_buf[irq_data->reg_offset / map->reg_stride] + &= ~irq_data->mask; d->wake_count++; } else { - if (d->wake_buf) - d->wake_buf[irq_data->reg_offset / map->reg_stride] - |= irq_data->mask; + d->wake_buf[irq_data->reg_offset / map->reg_stride] + |= irq_data->mask; d->wake_count--; } @@ -188,62 +171,6 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } } - /* - * Read in the statuses, using a single bulk read if possible - * in order to reduce the I/O overheads. - */ - if (!map->use_single_rw && map->reg_stride == 1 && - data->irq_reg_stride == 1) { - u8 *buf8 = data->status_reg_buf; - u16 *buf16 = data->status_reg_buf; - u32 *buf32 = data->status_reg_buf; - - BUG_ON(!data->status_reg_buf); - - ret = regmap_bulk_read(map, chip->status_base, - data->status_reg_buf, - chip->num_regs); - if (ret != 0) { - dev_err(map->dev, "Failed to read IRQ status: %d\n", - ret); - return IRQ_NONE; - } - - for (i = 0; i < data->chip->num_regs; i++) { - switch (map->format.val_bytes) { - case 1: - data->status_buf[i] = buf8[i]; - break; - case 2: - data->status_buf[i] = buf16[i]; - break; - case 4: - data->status_buf[i] = buf32[i]; - break; - default: - BUG(); - return IRQ_NONE; - } - } - - } else { - for (i = 0; i < data->chip->num_regs; i++) { - ret = regmap_read(map, chip->status_base + - (i * map->reg_stride - * data->irq_reg_stride), - &data->status_buf[i]); - - if (ret != 0) { - dev_err(map->dev, - "Failed to read IRQ status: %d\n", - ret); - if (chip->runtime_pm) - pm_runtime_put(map->dev); - return IRQ_NONE; - } - } - } - /* * Ignore masked IRQs and ack if we need to; we ack early so * there is no race between handling and acknowleding the @@ -252,6 +179,18 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) * doing a write per register. */ for (i = 0; i < data->chip->num_regs; i++) { + ret = regmap_read(map, chip->status_base + (i * map->reg_stride + * data->irq_reg_stride), + &data->status_buf[i]); + + if (ret != 0) { + dev_err(map->dev, "Failed to read IRQ status: %d\n", + ret); + if (chip->runtime_pm) + pm_runtime_put(map->dev); + return IRQ_NONE; + } + data->status_buf[i] &= ~data->mask_buf[i]; if (data->status_buf[i] && chip->ack_base) { @@ -377,6 +316,11 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, d->irq_chip = regmap_irq_chip; d->irq_chip.name = chip->name; + if (!chip->wake_base) { + d->irq_chip.irq_set_wake = NULL; + d->irq_chip.flags |= IRQCHIP_MASK_ON_SUSPEND | + IRQCHIP_SKIP_SET_WAKE; + } d->irq = irq; d->map = map; d->chip = chip; @@ -387,14 +331,6 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, else d->irq_reg_stride = 1; - if (!map->use_single_rw && map->reg_stride == 1 && - d->irq_reg_stride == 1) { - d->status_reg_buf = kmalloc(map->format.val_bytes * - chip->num_regs, GFP_KERNEL); - if (!d->status_reg_buf) - goto err_alloc; - } - mutex_init(&d->lock); for (i = 0; i < chip->num_irqs; i++) @@ -425,15 +361,8 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, d->wake_buf[i] = d->mask_buf_def[i]; reg = chip->wake_base + (i * map->reg_stride * d->irq_reg_stride); - - if (chip->wake_invert) - ret = regmap_update_bits(map, reg, - d->mask_buf_def[i], - 0); - else - ret = regmap_update_bits(map, reg, - d->mask_buf_def[i], - d->wake_buf[i]); + ret = regmap_update_bits(map, reg, d->wake_buf[i], + d->wake_buf[i]); if (ret != 0) { dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", reg, ret); @@ -472,7 +401,6 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, kfree(d->mask_buf_def); kfree(d->mask_buf); kfree(d->status_buf); - kfree(d->status_reg_buf); kfree(d); return ret; } @@ -494,7 +422,6 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d) kfree(d->wake_buf); kfree(d->mask_buf_def); kfree(d->mask_buf); - kfree(d->status_reg_buf); kfree(d->status_buf); kfree(d); } diff --git a/trunk/drivers/base/regmap/regmap-mmio.c b/trunk/drivers/base/regmap/regmap-mmio.c index f05fc74dd84a..98745dd77e8c 100644 --- a/trunk/drivers/base/regmap/regmap-mmio.c +++ b/trunk/drivers/base/regmap/regmap-mmio.c @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -26,6 +27,7 @@ struct regmap_mmio_context { void __iomem *regs; unsigned val_bytes; + struct clk *clk; }; static int regmap_mmio_gather_write(void *context, @@ -34,9 +36,16 @@ static int regmap_mmio_gather_write(void *context, { struct regmap_mmio_context *ctx = context; u32 offset; + int ret; BUG_ON(reg_size != 4); + if (ctx->clk) { + ret = clk_enable(ctx->clk); + if (ret < 0) + return ret; + } + offset = *(u32 *)reg; while (val_size) { @@ -64,6 +73,9 @@ static int regmap_mmio_gather_write(void *context, offset += ctx->val_bytes; } + if (ctx->clk) + clk_disable(ctx->clk); + return 0; } @@ -80,9 +92,16 @@ static int regmap_mmio_read(void *context, { struct regmap_mmio_context *ctx = context; u32 offset; + int ret; BUG_ON(reg_size != 4); + if (ctx->clk) { + ret = clk_enable(ctx->clk); + if (ret < 0) + return ret; + } + offset = *(u32 *)reg; while (val_size) { @@ -110,11 +129,20 @@ static int regmap_mmio_read(void *context, offset += ctx->val_bytes; } + if (ctx->clk) + clk_disable(ctx->clk); + return 0; } static void regmap_mmio_free_context(void *context) { + struct regmap_mmio_context *ctx = context; + + if (ctx->clk) { + clk_unprepare(ctx->clk); + clk_put(ctx->clk); + } kfree(context); } @@ -128,11 +156,14 @@ static struct regmap_bus regmap_mmio = { .val_format_endian_default = REGMAP_ENDIAN_NATIVE, }; -static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs, +static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, + const char *clk_id, + void __iomem *regs, const struct regmap_config *config) { struct regmap_mmio_context *ctx; int min_stride; + int ret; if (config->reg_bits != 32) return ERR_PTR(-EINVAL); @@ -179,37 +210,59 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs, ctx->regs = regs; ctx->val_bytes = config->val_bits / 8; + if (clk_id == NULL) + return ctx; + + ctx->clk = clk_get(dev, clk_id); + if (IS_ERR(ctx->clk)) { + ret = PTR_ERR(ctx->clk); + goto err_free; + } + + ret = clk_prepare(ctx->clk); + if (ret < 0) { + clk_put(ctx->clk); + goto err_free; + } + return ctx; + +err_free: + kfree(ctx); + + return ERR_PTR(ret); } /** - * regmap_init_mmio(): Initialise register map + * regmap_init_mmio_clk(): Initialise register map with register clock * * @dev: Device that will be interacted with + * @clk_id: register clock consumer ID * @regs: Pointer to memory-mapped IO region * @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_mmio(struct device *dev, - void __iomem *regs, - const struct regmap_config *config) +struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, + void __iomem *regs, + const struct regmap_config *config) { struct regmap_mmio_context *ctx; - ctx = regmap_mmio_gen_context(regs, config); + ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); if (IS_ERR(ctx)) return ERR_CAST(ctx); return regmap_init(dev, ®map_mmio, ctx, config); } -EXPORT_SYMBOL_GPL(regmap_init_mmio); +EXPORT_SYMBOL_GPL(regmap_init_mmio_clk); /** - * devm_regmap_init_mmio(): Initialise managed register map + * devm_regmap_init_mmio_clk(): Initialise managed register map with clock * * @dev: Device that will be interacted with + * @clk_id: register clock consumer ID * @regs: Pointer to memory-mapped IO region * @config: Configuration for register map * @@ -217,18 +270,18 @@ EXPORT_SYMBOL_GPL(regmap_init_mmio); * to a struct regmap. The regmap will be automatically freed by the * device management code. */ -struct regmap *devm_regmap_init_mmio(struct device *dev, - void __iomem *regs, - const struct regmap_config *config) +struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, + void __iomem *regs, + const struct regmap_config *config) { struct regmap_mmio_context *ctx; - ctx = regmap_mmio_gen_context(regs, config); + ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); if (IS_ERR(ctx)) return ERR_CAST(ctx); return devm_regmap_init(dev, ®map_mmio, ctx, config); } -EXPORT_SYMBOL_GPL(devm_regmap_init_mmio); +EXPORT_SYMBOL_GPL(devm_regmap_init_mmio_clk); MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/base/regmap/regmap-spi.c b/trunk/drivers/base/regmap/regmap-spi.c index 4c506bd940f3..ffa46a92ad33 100644 --- a/trunk/drivers/base/regmap/regmap-spi.c +++ b/trunk/drivers/base/regmap/regmap-spi.c @@ -15,21 +15,6 @@ #include #include -#include "internal.h" - -struct regmap_async_spi { - struct regmap_async core; - struct spi_message m; - struct spi_transfer t[2]; -}; - -static void regmap_spi_complete(void *data) -{ - struct regmap_async_spi *async = data; - - regmap_async_complete_cb(&async->core, async->m.status); -} - static int regmap_spi_write(void *context, const void *data, size_t count) { struct device *dev = context; @@ -55,43 +40,6 @@ static int regmap_spi_gather_write(void *context, return spi_sync(spi, &m); } -static int regmap_spi_async_write(void *context, - const void *reg, size_t reg_len, - const void *val, size_t val_len, - struct regmap_async *a) -{ - struct regmap_async_spi *async = container_of(a, - struct regmap_async_spi, - core); - struct device *dev = context; - struct spi_device *spi = to_spi_device(dev); - - async->t[0].tx_buf = reg; - async->t[0].len = reg_len; - async->t[1].tx_buf = val; - async->t[1].len = val_len; - - spi_message_init(&async->m); - spi_message_add_tail(&async->t[0], &async->m); - spi_message_add_tail(&async->t[1], &async->m); - - async->m.complete = regmap_spi_complete; - async->m.context = async; - - return spi_async(spi, &async->m); -} - -static struct regmap_async *regmap_spi_async_alloc(void) -{ - struct regmap_async_spi *async_spi; - - async_spi = kzalloc(sizeof(*async_spi), GFP_KERNEL); - if (!async_spi) - return NULL; - - return &async_spi->core; -} - static int regmap_spi_read(void *context, const void *reg, size_t reg_size, void *val, size_t val_size) @@ -105,8 +53,6 @@ static int regmap_spi_read(void *context, static struct regmap_bus regmap_spi = { .write = regmap_spi_write, .gather_write = regmap_spi_gather_write, - .async_write = regmap_spi_async_write, - .async_alloc = regmap_spi_async_alloc, .read = regmap_spi_read, .read_flag_mask = 0x80, }; diff --git a/trunk/drivers/base/regmap/regmap.c b/trunk/drivers/base/regmap/regmap.c index b1d962434cb2..f00b059c057a 100644 --- a/trunk/drivers/base/regmap/regmap.c +++ b/trunk/drivers/base/regmap/regmap.c @@ -16,7 +16,6 @@ #include #include #include -#include #define CREATE_TRACE_POINTS #include @@ -35,22 +34,6 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, unsigned int mask, unsigned int val, bool *change); -static int _regmap_bus_read(void *context, unsigned int reg, - unsigned int *val); -static int _regmap_bus_formatted_write(void *context, unsigned int reg, - unsigned int val); -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) @@ -440,10 +423,6 @@ struct regmap *regmap_init(struct device *dev, map->cache_type = config->cache_type; map->name = config->name; - spin_lock_init(&map->async_lock); - INIT_LIST_HEAD(&map->async_list); - init_waitqueue_head(&map->async_waitq); - if (config->read_flag_mask || config->write_flag_mask) { map->read_flag_mask = config->read_flag_mask; map->write_flag_mask = config->write_flag_mask; @@ -451,8 +430,6 @@ struct regmap *regmap_init(struct device *dev, map->read_flag_mask = bus->read_flag_mask; } - map->reg_read = _regmap_bus_read; - reg_endian = config->reg_format_endian; if (reg_endian == REGMAP_ENDIAN_DEFAULT) reg_endian = bus->reg_format_endian_default; @@ -523,12 +500,6 @@ struct regmap *regmap_init(struct device *dev, } break; - case 24: - if (reg_endian != REGMAP_ENDIAN_BIG) - goto err_map; - map->format.format_reg = regmap_format_24; - break; - case 32: switch (reg_endian) { case REGMAP_ENDIAN_BIG: @@ -604,11 +575,6 @@ struct regmap *regmap_init(struct device *dev, goto err_map; } - if (map->format.format_write) - map->reg_write = _regmap_bus_formatted_write; - else if (map->format.format_val) - map->reg_write = _regmap_bus_raw_write; - map->range_tree = RB_ROOT; for (i = 0; i < config->num_ranges; i++) { const struct regmap_range_cfg *range_cfg = &config->ranges[i]; @@ -904,13 +870,10 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg, } static int _regmap_raw_write(struct regmap *map, unsigned int reg, - const void *val, size_t val_len, bool async) + const void *val, size_t val_len) { struct regmap_range_node *range; - unsigned long flags; u8 *u8 = map->work_buf; - void *work_val = map->work_buf + map->format.reg_bytes + - map->format.pad_bytes; void *buf; int ret = -ENOTSUPP; size_t len; @@ -955,7 +918,7 @@ static 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, async); + map->format.val_bytes); if (ret != 0) return ret; @@ -978,50 +941,6 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, u8[0] |= map->write_flag_mask; - if (async && map->bus->async_write) { - struct regmap_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; - } - - 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); - - 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_del(&async->list); - spin_unlock_irqrestore(&map->async_lock, flags); - - kfree(async->work_buf); - kfree(async); - } - } - trace_regmap_hw_write_start(map->dev, reg, val_len / map->format.val_bytes); @@ -1029,7 +948,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, * send the work_buf directly, otherwise try to do a gather * write. */ - if (val == work_val) + if (val == (map->work_buf + map->format.pad_bytes + + map->format.reg_bytes)) ret = map->bus->write(map->bus_context, map->work_buf, map->format.reg_bytes + map->format.pad_bytes + @@ -1061,54 +981,12 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, return ret; } -static int _regmap_bus_formatted_write(void *context, unsigned int reg, - unsigned int val) -{ - int ret; - struct regmap_range_node *range; - struct regmap *map = context; - - BUG_ON(!map->format.format_write); - - range = _regmap_range_lookup(map, reg); - if (range) { - ret = _regmap_select_page(map, ®, range, 1); - if (ret != 0) - return ret; - } - - map->format.format_write(map, reg, val); - - trace_regmap_hw_write_start(map->dev, reg, 1); - - ret = map->bus->write(map->bus_context, map->work_buf, - map->format.buf_size); - - trace_regmap_hw_write_done(map->dev, reg, 1); - - return ret; -} - -static int _regmap_bus_raw_write(void *context, unsigned int reg, - unsigned int val) -{ - struct regmap *map = context; - - BUG_ON(!map->format.format_val); - - map->format.format_val(map->work_buf + map->format.reg_bytes - + map->format.pad_bytes, val, 0); - return _regmap_raw_write(map, reg, - map->work_buf + - map->format.reg_bytes + - map->format.pad_bytes, - map->format.val_bytes, false); -} - int _regmap_write(struct regmap *map, unsigned int reg, unsigned int val) { + struct regmap_range_node *range; int ret; + BUG_ON(!map->format.format_write && !map->format.format_val); if (!map->cache_bypass && map->format.format_write) { ret = regcache_write(map, reg, val); @@ -1127,7 +1005,33 @@ int _regmap_write(struct regmap *map, unsigned int reg, trace_regmap_reg_write(map->dev, reg, val); - return map->reg_write(map, reg, val); + if (map->format.format_write) { + range = _regmap_range_lookup(map, reg); + if (range) { + ret = _regmap_select_page(map, ®, range, 1); + if (ret != 0) + return ret; + } + + map->format.format_write(map, reg, val); + + trace_regmap_hw_write_start(map->dev, reg, 1); + + ret = map->bus->write(map->bus_context, map->work_buf, + map->format.buf_size); + + trace_regmap_hw_write_done(map->dev, reg, 1); + + return ret; + } else { + map->format.format_val(map->work_buf + map->format.reg_bytes + + map->format.pad_bytes, val, 0); + return _regmap_raw_write(map, reg, + map->work_buf + + map->format.reg_bytes + + map->format.pad_bytes, + map->format.val_bytes); + } } /** @@ -1185,7 +1089,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, false); + ret = _regmap_raw_write(map, reg, val, val_len); map->unlock(map->lock_arg); @@ -1241,15 +1145,14 @@ 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); + 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, - false); + ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); } if (val_bytes != 1) @@ -1261,48 +1164,6 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, } EXPORT_SYMBOL_GPL(regmap_bulk_write); -/** - * regmap_raw_write_async(): Write raw values to one or more registers - * asynchronously - * - * @map: Register map to write to - * @reg: Initial register to write to - * @val: Block of data to be written, laid out for direct transmission to the - * device. Must be valid until regmap_async_complete() is called. - * @val_len: Length of data pointed to by val. - * - * This function is intended to be used for things like firmware - * download where a large block of data needs to be transferred to the - * device. No formatting will be done on the data provided. - * - * If supported by the underlying bus the write will be scheduled - * asynchronously, helping maximise I/O speed on higher speed buses - * like SPI. regmap_async_complete() can be called to ensure that all - * asynchrnous writes have been completed. - * - * A value of zero will be returned on success, a negative errno will - * be returned in error cases. - */ -int regmap_raw_write_async(struct regmap *map, unsigned int reg, - const void *val, size_t val_len) -{ - int ret; - - if (val_len % map->format.val_bytes) - return -EINVAL; - if (reg % map->reg_stride) - return -EINVAL; - - map->lock(map->lock_arg); - - ret = _regmap_raw_write(map, reg, val, val_len, true); - - map->unlock(map->lock_arg); - - return ret; -} -EXPORT_SYMBOL_GPL(regmap_raw_write_async); - static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, unsigned int val_len) { @@ -1341,27 +1202,10 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, return ret; } -static int _regmap_bus_read(void *context, unsigned int reg, - unsigned int *val) -{ - int ret; - struct regmap *map = context; - - if (!map->format.parse_val) - return -EINVAL; - - ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); - if (ret == 0) - *val = map->format.parse_val(map->work_buf); - - return ret; -} - static int _regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) { int ret; - BUG_ON(!map->reg_read); if (!map->cache_bypass) { ret = regcache_read(map, reg, val); @@ -1369,22 +1213,27 @@ static int _regmap_read(struct regmap *map, unsigned int reg, return 0; } + if (!map->format.parse_val) + return -EINVAL; + if (map->cache_only) return -EBUSY; - ret = map->reg_read(map, reg, val); + ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); if (ret == 0) { + *val = map->format.parse_val(map->work_buf); + #ifdef LOG_DEVICE if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) dev_info(map->dev, "%x => %x\n", reg, *val); #endif trace_regmap_reg_read(map->dev, reg, *val); - - if (!map->cache_bypass) - regcache_write(map, reg, *val); } + if (ret == 0 && !map->cache_bypass) + regcache_write(map, reg, *val); + return ret; } @@ -1601,68 +1450,6 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg, } EXPORT_SYMBOL_GPL(regmap_update_bits_check); -void regmap_async_complete_cb(struct regmap_async *async, int ret) -{ - struct regmap *map = async->map; - bool wake; - - spin_lock(&map->async_lock); - - list_del(&async->list); - wake = list_empty(&map->async_list); - - if (ret != 0) - map->async_ret = ret; - - spin_unlock(&map->async_lock); - - schedule_work(&async->cleanup); - - if (wake) - wake_up(&map->async_waitq); -} -EXPORT_SYMBOL_GPL(regmap_async_complete_cb); - -static int regmap_async_is_done(struct regmap *map) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&map->async_lock, flags); - ret = list_empty(&map->async_list); - spin_unlock_irqrestore(&map->async_lock, flags); - - return ret; -} - -/** - * regmap_async_complete: Ensure all asynchronous I/O has completed. - * - * @map: Map to operate on. - * - * Blocks until any pending asynchronous I/O has completed. Returns - * an error code for any failed I/O operations. - */ -int regmap_async_complete(struct regmap *map) -{ - unsigned long flags; - int ret; - - /* Nothing to do with no async support */ - if (!map->bus->async_write) - return 0; - - wait_event(map->async_waitq, regmap_async_is_done(map)); - - spin_lock_irqsave(&map->async_lock, flags); - ret = map->async_ret; - map->async_ret = 0; - spin_unlock_irqrestore(&map->async_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(regmap_async_complete); - /** * regmap_register_patch: Register and apply register updates to be applied * on device initialistion diff --git a/trunk/drivers/mfd/wm5102-tables.c b/trunk/drivers/mfd/wm5102-tables.c index f6fcb87b3504..1133a64c2dc9 100644 --- a/trunk/drivers/mfd/wm5102-tables.c +++ b/trunk/drivers/mfd/wm5102-tables.c @@ -96,7 +96,6 @@ const struct regmap_irq_chip wm5102_aod = { .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, .ack_base = ARIZONA_AOD_IRQ1, .wake_base = ARIZONA_WAKE_CONTROL, - .wake_invert = 1, .num_regs = 1, .irqs = wm5102_aod_irqs, .num_irqs = ARRAY_SIZE(wm5102_aod_irqs), diff --git a/trunk/drivers/mfd/wm5110-tables.c b/trunk/drivers/mfd/wm5110-tables.c index c41599815299..adda6b10b90d 100644 --- a/trunk/drivers/mfd/wm5110-tables.c +++ b/trunk/drivers/mfd/wm5110-tables.c @@ -255,7 +255,6 @@ const struct regmap_irq_chip wm5110_aod = { .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, .ack_base = ARIZONA_AOD_IRQ1, .wake_base = ARIZONA_WAKE_CONTROL, - .wake_invert = 1, .num_regs = 1, .irqs = wm5110_aod_irqs, .num_irqs = ARRAY_SIZE(wm5110_aod_irqs), diff --git a/trunk/include/linux/regmap.h b/trunk/include/linux/regmap.h index 9e790f956025..f0480a3297e4 100644 --- a/trunk/include/linux/regmap.h +++ b/trunk/include/linux/regmap.h @@ -28,8 +28,7 @@ struct regmap_range_cfg; enum regcache_type { REGCACHE_NONE, REGCACHE_RBTREE, - REGCACHE_COMPRESSED, - REGCACHE_FLAT, + REGCACHE_COMPRESSED }; /** @@ -236,21 +235,14 @@ struct regmap_range_cfg { unsigned int window_len; }; -struct regmap_async; - typedef int (*regmap_hw_write)(void *context, const void *data, size_t count); typedef int (*regmap_hw_gather_write)(void *context, const void *reg, size_t reg_len, const void *val, size_t val_len); -typedef int (*regmap_hw_async_write)(void *context, - const void *reg, size_t reg_len, - const void *val, size_t val_len, - struct regmap_async *async); typedef int (*regmap_hw_read)(void *context, const void *reg_buf, size_t reg_size, void *val_buf, size_t val_size); -typedef struct regmap_async *(*regmap_hw_async_alloc)(void); typedef void (*regmap_hw_free_context)(void *context); /** @@ -263,11 +255,8 @@ typedef void (*regmap_hw_free_context)(void *context); * @write: Write operation. * @gather_write: Write operation with split register/value, return -ENOTSUPP * if not implemented on a given device. - * @async_write: Write operation which completes asynchronously, optional and - * must serialise with respect to non-async I/O. * @read: Read operation. Data is returned in the buffer used to transmit * data. - * @async_alloc: Allocate a regmap_async() structure. * @read_flag_mask: Mask to be set in the top byte of the register when doing * a read. * @reg_format_endian_default: Default endianness for formatted register @@ -276,16 +265,13 @@ typedef void (*regmap_hw_free_context)(void *context); * @val_format_endian_default: Default endianness for formatted register * values. Used when the regmap_config specifies DEFAULT. If this is * DEFAULT, BIG is assumed. - * @async_size: Size of struct used for async work. */ struct regmap_bus { bool fast_io; regmap_hw_write write; regmap_hw_gather_write gather_write; - regmap_hw_async_write async_write; regmap_hw_read read; regmap_hw_free_context free_context; - regmap_hw_async_alloc async_alloc; u8 read_flag_mask; enum regmap_endian reg_format_endian_default; enum regmap_endian val_format_endian_default; @@ -299,9 +285,9 @@ struct regmap *regmap_init_i2c(struct i2c_client *i2c, const struct regmap_config *config); struct regmap *regmap_init_spi(struct spi_device *dev, const struct regmap_config *config); -struct regmap *regmap_init_mmio(struct device *dev, - void __iomem *regs, - const struct regmap_config *config); +struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, + void __iomem *regs, + const struct regmap_config *config); struct regmap *devm_regmap_init(struct device *dev, const struct regmap_bus *bus, @@ -311,9 +297,44 @@ struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, const struct regmap_config *config); struct regmap *devm_regmap_init_spi(struct spi_device *dev, const struct regmap_config *config); -struct regmap *devm_regmap_init_mmio(struct device *dev, - void __iomem *regs, - const struct regmap_config *config); +struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, + void __iomem *regs, + const struct regmap_config *config); + +/** + * regmap_init_mmio(): Initialise register map + * + * @dev: Device that will be interacted with + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +static inline struct regmap *regmap_init_mmio(struct device *dev, + void __iomem *regs, + const struct regmap_config *config) +{ + return regmap_init_mmio_clk(dev, NULL, regs, config); +} + +/** + * devm_regmap_init_mmio(): Initialise managed register map + * + * @dev: Device that will be interacted with + * @regs: Pointer to memory-mapped IO region + * @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. + */ +static inline struct regmap *devm_regmap_init_mmio(struct device *dev, + void __iomem *regs, + const struct regmap_config *config) +{ + return devm_regmap_init_mmio_clk(dev, NULL, regs, config); +} void regmap_exit(struct regmap *map); int regmap_reinit_cache(struct regmap *map, @@ -324,8 +345,6 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, const void *val, size_t val_len); int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, size_t val_count); -int regmap_raw_write_async(struct regmap *map, unsigned int reg, - const void *val, size_t val_len); int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, size_t val_len); @@ -337,7 +356,6 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg, unsigned int mask, unsigned int val, bool *change); int regmap_get_val_bytes(struct regmap *map); -int regmap_async_complete(struct regmap *map); int regcache_sync(struct regmap *map); int regcache_sync_region(struct regmap *map, unsigned int min, @@ -398,7 +416,6 @@ struct regmap_irq_chip { unsigned int wake_base; unsigned int irq_reg_stride; unsigned int mask_invert; - unsigned int wake_invert; bool runtime_pm; int num_regs; @@ -440,13 +457,6 @@ static inline int regmap_raw_write(struct regmap *map, unsigned int reg, return -EINVAL; } -static inline int regmap_raw_write_async(struct regmap *map, unsigned int reg, - const void *val, size_t val_len) -{ - WARN_ONCE(1, "regmap API is disabled"); - return -EINVAL; -} - static inline int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, size_t val_count) { @@ -525,11 +535,6 @@ static inline void regcache_mark_dirty(struct regmap *map) WARN_ONCE(1, "regmap API is disabled"); } -static inline void regmap_async_complete(struct regmap *map) -{ - WARN_ONCE(1, "regmap API is disabled"); -} - static inline int regmap_register_patch(struct regmap *map, const struct reg_default *regs, int num_regs)