From 52cd22f93453192754ff6ebc1bc91cf564f57c30 Mon Sep 17 00:00:00 2001
From: Philipp Zabel
Date: Thu, 14 Feb 2013 17:39:08 +0100
Subject: [PATCH] --- yaml --- r: 350382 b: refs/heads/master c:
878ec67b3ac528a2b6d44055f049cdbb9cfda30c h: refs/heads/master v: v3
---
[refs] | 2 +-
trunk/drivers/base/regmap/Makefile | 2 +-
trunk/drivers/base/regmap/internal.h | 20 --
trunk/drivers/base/regmap/regcache-flat.c | 72 -----
trunk/drivers/base/regmap/regcache.c | 1 -
trunk/drivers/base/regmap/regmap-debugfs.c | 50 ++--
trunk/drivers/base/regmap/regmap-irq.c | 125 ++-------
trunk/drivers/base/regmap/regmap-mmio.c | 79 +++++-
trunk/drivers/base/regmap/regmap-spi.c | 54 ----
trunk/drivers/base/regmap/regmap.c | 307 ++++-----------------
trunk/drivers/mfd/wm5102-tables.c | 1 -
trunk/drivers/mfd/wm5110-tables.c | 1 -
trunk/include/linux/regmap.h | 79 +++---
13 files changed, 201 insertions(+), 592 deletions(-)
delete mode 100644 trunk/drivers/base/regmap/regcache-flat.c
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)