Merge remote-tracking branch 'regmap/topic/no-bus' into regmap-next
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 14 Feb 2013 17:11:09 +0000 (17:11 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 14 Feb 2013 17:11:09 +0000 (17:11 +0000)
1  2 
drivers/base/regmap/internal.h
drivers/base/regmap/regmap.c
include/linux/regmap.h

index 70ca270b77e2838b0ac87f398d3e2ee5576637cf,b55fde5d216a911950104c0ae915c3f7199a0600..5a22bd33ce3d7704df94411f216009ee24019336
@@@ -16,7 -16,6 +16,7 @@@
  #include <linux/regmap.h>
  #include <linux/fs.h>
  #include <linux/list.h>
 +#include <linux/wait.h>
  
  struct regmap;
  struct regcache_ops;
@@@ -26,7 -25,6 +26,7 @@@ struct regmap_debugfs_off_cache 
        off_t min;
        off_t max;
        unsigned int base_reg;
 +      unsigned int max_reg;
  };
  
  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;
        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;
@@@ -91,6 -77,8 +91,8 @@@
        int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
        int (*reg_write)(void *context, unsigned int reg, unsigned int val);
  
+       bool defer_caching;
        u8 read_flag_mask;
        u8 write_flag_mask;
  
@@@ -192,10 -180,7 +194,10 @@@ bool regcache_set_val(void *base, unsig
                      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
index b1d962434cb20780e2116fe376c5cb043fe74a89,9592030a0dc3b82c2bde7b14943cdc5317fc3d6d..3d2367501fd0521ee4e472df6126b6ea25ee09a3
@@@ -16,7 -16,6 +16,7 @@@
  #include <linux/mutex.h>
  #include <linux/err.h>
  #include <linux/rbtree.h>
 +#include <linux/sched.h>
  
  #define CREATE_TRACE_POINTS
  #include <trace/events/regmap.h>
@@@ -42,15 -41,6 +42,15 @@@ static int _regmap_bus_formatted_write(
  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)
@@@ -389,7 -379,7 +389,7 @@@ struct regmap *regmap_init(struct devic
        enum regmap_endian reg_endian, val_endian;
        int i, j;
  
-       if (!bus || !config)
+       if (!config)
                goto err;
  
        map = kzalloc(sizeof(*map), GFP_KERNEL);
                map->unlock = config->unlock;
                map->lock_arg = config->lock_arg;
        } else {
-               if (bus->fast_io) {
+               if ((bus && bus->fast_io) ||
+                   config->fast_io) {
                        spin_lock_init(&map->spinlock);
                        map->lock = regmap_lock_spinlock;
                        map->unlock = regmap_unlock_spinlock;
        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;
-       } else {
+       } else if (bus) {
                map->read_flag_mask = bus->read_flag_mask;
        }
  
-       map->reg_read = _regmap_bus_read;
+       if (!bus) {
+               map->reg_read  = config->reg_read;
+               map->reg_write = config->reg_write;
+               map->defer_caching = false;
+               goto skip_format_initialization;
+       } else {
+               map->reg_read  = _regmap_bus_read;
+       }
  
        reg_endian = config->reg_format_endian;
        if (reg_endian == REGMAP_ENDIAN_DEFAULT)
                }
                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:
                goto err_map;
        }
  
-       if (map->format.format_write)
+       if (map->format.format_write) {
+               map->defer_caching = false;
                map->reg_write = _regmap_bus_formatted_write;
-       else if (map->format.format_val)
+       } else if (map->format.format_val) {
+               map->defer_caching = true;
                map->reg_write = _regmap_bus_raw_write;
+       }
+ skip_format_initialization:
  
        map->range_tree = RB_ROOT;
        for (i = 0; i < config->num_ranges; i++) {
@@@ -810,7 -804,7 +824,7 @@@ void regmap_exit(struct regmap *map
        regcache_exit(map);
        regmap_debugfs_exit(map);
        regmap_range_exit(map);
-       if (map->bus->free_context)
+       if (map->bus && map->bus->free_context)
                map->bus->free_context(map->bus_context);
        kfree(map->work_buf);
        kfree(map);
@@@ -904,18 -898,17 +918,20 @@@ static int _regmap_select_page(struct r
  }
  
  static 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;
        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;
        int i;
  
+       BUG_ON(!map->bus);
        /* Check for unwritable registers before we start */
        if (map->writeable_reg)
                for (i = 0; i < val_len / map->format.val_bytes; i++)
                        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;
  
  
        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);
  
         * send the work_buf directly, otherwise try to do a gather
         * write.
         */
 -      if (val == (map->work_buf + map->format.pad_bytes +
 -                  map->format.reg_bytes))
 +      if (val == work_val)
                ret = map->bus->write(map->bus_context, map->work_buf,
                                      map->format.reg_bytes +
                                      map->format.pad_bytes +
@@@ -1068,7 -1018,7 +1084,7 @@@ static int _regmap_bus_formatted_write(
        struct regmap_range_node *range;
        struct regmap *map = context;
  
-       BUG_ON(!map->format.format_write);
+       BUG_ON(!map->bus || !map->format.format_write);
  
        range = _regmap_range_lookup(map, reg);
        if (range) {
@@@ -1094,7 -1044,7 +1110,7 @@@ static int _regmap_bus_raw_write(void *
  {
        struct regmap *map = context;
  
-       BUG_ON(!map->format.format_val);
+       BUG_ON(!map->bus || !map->format.format_val);
  
        map->format.format_val(map->work_buf + map->format.reg_bytes
                               + map->format.pad_bytes, val, 0);
                                 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)
+ {
+       return (map->bus) ? map : map->bus_context;
+ }
  int _regmap_write(struct regmap *map, unsigned int reg,
                  unsigned int val)
  {
        int ret;
+       void *context = _regmap_map_get_context(map);
  
-       if (!map->cache_bypass && map->format.format_write) {
+       if (!map->cache_bypass && !map->defer_caching) {
                ret = regcache_write(map, reg, val);
                if (ret != 0)
                        return ret;
  
        trace_regmap_reg_write(map->dev, reg, val);
  
-       return map->reg_write(map, reg, val);
+       return map->reg_write(context, reg, val);
  }
  
  /**
@@@ -1178,6 -1134,8 +1200,8 @@@ int regmap_raw_write(struct regmap *map
  {
        int ret;
  
+       if (!map->bus)
+               return -EINVAL;
        if (val_len % map->format.val_bytes)
                return -EINVAL;
        if (reg % map->reg_stride)
  
        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);
  
@@@ -1202,7 -1160,7 +1226,7 @@@ EXPORT_SYMBOL_GPL(regmap_raw_write)
   * @val_count: Number of registers to write
   *
   * This function is intended to be used for writing a large block of
 - * data to be device either in single transfer or multiple transfer.
 + * data to the device either in single transfer or multiple transfer.
   *
   * A value of zero will be returned on success, a negative errno will
   * be returned in error cases.
@@@ -1214,6 -1172,8 +1238,8 @@@ int regmap_bulk_write(struct regmap *ma
        size_t val_bytes = map->format.val_bytes;
        void *wval;
  
+       if (!map->bus)
+               return -EINVAL;
        if (!map->format.parse_val)
                return -EINVAL;
        if (reg % map->reg_stride)
        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);
 +              ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count,
 +                                      false);
        }
  
        if (val_bytes != 1)
  }
  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)
  {
        u8 *u8 = map->work_buf;
        int ret;
  
+       BUG_ON(!map->bus);
        range = _regmap_range_lookup(map, reg);
        if (range) {
                ret = _regmap_select_page(map, &reg, range,
@@@ -1361,6 -1280,8 +1389,8 @@@ static int _regmap_read(struct regmap *
                        unsigned int *val)
  {
        int ret;
+       void *context = _regmap_map_get_context(map);
        BUG_ON(!map->reg_read);
  
        if (!map->cache_bypass) {
        if (map->cache_only)
                return -EBUSY;
  
-       ret = map->reg_read(map, reg, val);
+       ret = map->reg_read(context, reg, val);
        if (ret == 0) {
  #ifdef LOG_DEVICE
                if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
@@@ -1434,6 -1355,8 +1464,8 @@@ int regmap_raw_read(struct regmap *map
        unsigned int v;
        int ret, i;
  
+       if (!map->bus)
+               return -EINVAL;
        if (val_len % map->format.val_bytes)
                return -EINVAL;
        if (reg % map->reg_stride)
@@@ -1485,6 -1408,8 +1517,8 @@@ int regmap_bulk_read(struct regmap *map
        size_t val_bytes = map->format.val_bytes;
        bool vol = regmap_volatile_range(map, reg, val_count);
  
+       if (!map->bus)
+               return -EINVAL;
        if (!map->format.parse_val)
                return -EINVAL;
        if (reg % map->reg_stride)
@@@ -1601,68 -1526,6 +1635,68 @@@ int regmap_update_bits_check(struct 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 --combined include/linux/regmap.h
index 017b3bd085a2cd7c499d48c81f6d1f25312d1b46,28dde941c78353d10e5815e948304832bc55bc8b..bf77dfdabef9559b021503b9163fd548ac8553de
@@@ -28,8 -28,7 +28,8 @@@ struct regmap_range_cfg
  enum regcache_type {
        REGCACHE_NONE,
        REGCACHE_RBTREE,
 -      REGCACHE_COMPRESSED
 +      REGCACHE_COMPRESSED,
 +      REGCACHE_FLAT,
  };
  
  /**
@@@ -128,7 -127,18 +128,18 @@@ typedef void (*regmap_unlock)(void *)
   * @lock_arg:   this field is passed as the only argument of lock/unlock
   *              functions (ignored in case regular lock/unlock functions
   *              are not overridden).
-  *
+  * @reg_read:   Optional callback that if filled will be used to perform
+  *              all the reads from the registers. Should only be provided for
+  *              devices whos read operation cannot be represented as a simple read
+  *              operation on a bus such as SPI, I2C, etc. Most of the devices do
+  *              not need this.
+  * @reg_write:          Same as above for writing.
+  * @fast_io:    Register IO is fast. Use a spinlock instead of a mutex
+  *              to perform locking. This field is ignored if custom lock/unlock
+  *              functions are used (see fields lock/unlock of struct regmap_config).
+  *              This field is a duplicate of a similar file in
+  *              'struct regmap_bus' and serves exact same purpose.
+  *               Use it only for "no-bus" cases.
   * @max_register: Optional, specifies the maximum valid register index.
   * @wr_table:     Optional, points to a struct regmap_access_table specifying
   *                valid ranges for write access.
@@@ -178,6 -188,11 +189,11 @@@ struct regmap_config 
        regmap_unlock unlock;
        void *lock_arg;
  
+       int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
+       int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+       bool fast_io;
        unsigned int max_register;
        const struct regmap_access_table *wr_table;
        const struct regmap_access_table *rd_table;
@@@ -236,21 -251,14 +252,21 @@@ 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);
  
  /**
   * @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
   * @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 -301,9 +315,9 @@@ struct regmap *regmap_init_i2c(struct i
                               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,44 -313,9 +327,44 @@@ struct regmap *devm_regmap_init_i2c(str
                                    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,
@@@ -359,8 -326,6 +375,8 @@@ int regmap_raw_write(struct regmap *map
                     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);
@@@ -372,7 -337,6 +388,7 @@@ int regmap_update_bits_check(struct 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,
@@@ -433,7 -397,6 +449,7 @@@ 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;
@@@ -475,13 -438,6 +491,13 @@@ static inline int regmap_raw_write(stru
        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)
  {
@@@ -560,11 -516,6 +576,11 @@@ static inline void regcache_mark_dirty(
        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)