Skip to content

Commit

Permalink
Merge tag 'regmap-v3.20' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/broonie/regmap

Pull regmap updates from Mark Brown:
 "A very quiet release for regmap this time around:

   - Fix an endianness issue for I2C devices connected via SMBus where
     we were getting two layers both trying to do endianness handling.
   - Use a union to reduce the size of the regmap struct.
   - A couple of smaller fixes"

* tag 'regmap-v3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
  regmap: Fix i2c word access when using SMBus access functions
  regmap: Export regmap_get_val_endian
  regmap: ac97: Clean up indentation
  regmap: correct the description of structure element in reg_field
  regmap: Move spinlock_flags into the union
  • Loading branch information
Linus Torvalds committed Feb 9, 2015
2 parents 5c30c3c + 1aff031 commit f381f90
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 9 deletions.
10 changes: 8 additions & 2 deletions drivers/base/regmap/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ struct regmap_async {
struct regmap {
union {
struct mutex mutex;
spinlock_t spinlock;
struct {
spinlock_t spinlock;
unsigned long spinlock_flags;
};
};
unsigned long spinlock_flags;
regmap_lock lock;
regmap_unlock unlock;
void *lock_arg; /* This is passed to lock/unlock functions */
Expand Down Expand Up @@ -233,6 +235,10 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,

void regmap_async_complete_cb(struct regmap_async *async, int ret);

enum regmap_endian regmap_get_val_endian(struct device *dev,
const struct regmap_bus *bus,
const struct regmap_config *config);

extern struct regcache_ops regcache_rbtree_ops;
extern struct regcache_ops regcache_lzo_ops;
extern struct regcache_ops regcache_flat_ops;
Expand Down
4 changes: 2 additions & 2 deletions drivers/base/regmap/regmap-ac97.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ static int regmap_ac97_reg_write(void *context, unsigned int reg,
}

static const struct regmap_bus ac97_regmap_bus = {
.reg_write = regmap_ac97_reg_write,
.reg_read = regmap_ac97_reg_read,
.reg_write = regmap_ac97_reg_write,
.reg_read = regmap_ac97_reg_read,
};

/**
Expand Down
46 changes: 45 additions & 1 deletion drivers/base/regmap/regmap-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/i2c.h>
#include <linux/module.h>

#include "internal.h"

static int regmap_smbus_byte_reg_read(void *context, unsigned int reg,
unsigned int *val)
Expand Down Expand Up @@ -87,6 +88,42 @@ static struct regmap_bus regmap_smbus_word = {
.reg_read = regmap_smbus_word_reg_read,
};

static int regmap_smbus_word_read_swapped(void *context, unsigned int reg,
unsigned int *val)
{
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
int ret;

if (reg > 0xff)
return -EINVAL;

ret = i2c_smbus_read_word_swapped(i2c, reg);
if (ret < 0)
return ret;

*val = ret;

return 0;
}

static int regmap_smbus_word_write_swapped(void *context, unsigned int reg,
unsigned int val)
{
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);

if (val > 0xffff || reg > 0xff)
return -EINVAL;

return i2c_smbus_write_word_swapped(i2c, reg, val);
}

static struct regmap_bus regmap_smbus_word_swapped = {
.reg_write = regmap_smbus_word_write_swapped,
.reg_read = regmap_smbus_word_read_swapped,
};

static int regmap_i2c_write(void *context, const void *data, size_t count)
{
struct device *dev = context;
Expand Down Expand Up @@ -180,7 +217,14 @@ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
else if (config->val_bits == 16 && config->reg_bits == 8 &&
i2c_check_functionality(i2c->adapter,
I2C_FUNC_SMBUS_WORD_DATA))
return &regmap_smbus_word;
switch (regmap_get_val_endian(&i2c->dev, NULL, config)) {
case REGMAP_ENDIAN_LITTLE:
return &regmap_smbus_word;
case REGMAP_ENDIAN_BIG:
return &regmap_smbus_word_swapped;
default: /* everything else is not supported */
break;
}
else if (config->val_bits == 8 && config->reg_bits == 8 &&
i2c_check_functionality(i2c->adapter,
I2C_FUNC_SMBUS_BYTE_DATA))
Expand Down
7 changes: 4 additions & 3 deletions drivers/base/regmap/regmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,9 +473,9 @@ static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
return REGMAP_ENDIAN_BIG;
}

static enum regmap_endian regmap_get_val_endian(struct device *dev,
const struct regmap_bus *bus,
const struct regmap_config *config)
enum regmap_endian regmap_get_val_endian(struct device *dev,
const struct regmap_bus *bus,
const struct regmap_config *config)
{
struct device_node *np;
enum regmap_endian endian;
Expand Down Expand Up @@ -513,6 +513,7 @@ static enum regmap_endian regmap_get_val_endian(struct device *dev,
/* Use this if no other value was found */
return REGMAP_ENDIAN_BIG;
}
EXPORT_SYMBOL_GPL(regmap_get_val_endian);

/**
* regmap_init(): Initialise register map
Expand Down
2 changes: 1 addition & 1 deletion include/linux/regmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ bool regmap_reg_in_ranges(unsigned int reg,
*
* @reg: Offset of the register within the regmap bank
* @lsb: lsb of the register field.
* @reg: msb of the register field.
* @msb: msb of the register field.
* @id_size: port size if it has some ports
* @id_offset: address offset for each ports
*/
Expand Down

0 comments on commit f381f90

Please sign in to comment.