Merge remote-tracking branch 'regmap/topic/table' into regmap-next
This commit is contained in:
commit
8e24a6e696
@ -69,6 +69,10 @@ struct regmap {
|
|||||||
bool (*readable_reg)(struct device *dev, unsigned int reg);
|
bool (*readable_reg)(struct device *dev, unsigned int reg);
|
||||||
bool (*volatile_reg)(struct device *dev, unsigned int reg);
|
bool (*volatile_reg)(struct device *dev, unsigned int reg);
|
||||||
bool (*precious_reg)(struct device *dev, unsigned int reg);
|
bool (*precious_reg)(struct device *dev, unsigned int reg);
|
||||||
|
const struct regmap_access_table *wr_table;
|
||||||
|
const struct regmap_access_table *rd_table;
|
||||||
|
const struct regmap_access_table *volatile_table;
|
||||||
|
const struct regmap_access_table *precious_table;
|
||||||
|
|
||||||
u8 read_flag_mask;
|
u8 read_flag_mask;
|
||||||
u8 write_flag_mask;
|
u8 write_flag_mask;
|
||||||
|
@ -34,6 +34,36 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
|||||||
unsigned int mask, unsigned int val,
|
unsigned int mask, unsigned int val,
|
||||||
bool *change);
|
bool *change);
|
||||||
|
|
||||||
|
bool regmap_reg_in_ranges(unsigned int reg,
|
||||||
|
const struct regmap_range *ranges,
|
||||||
|
unsigned int nranges)
|
||||||
|
{
|
||||||
|
const struct regmap_range *r;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0, r = ranges; i < nranges; i++, r++)
|
||||||
|
if (regmap_reg_in_range(reg, r))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(regmap_reg_in_ranges);
|
||||||
|
|
||||||
|
static bool _regmap_check_range_table(struct regmap *map,
|
||||||
|
unsigned int reg,
|
||||||
|
const struct regmap_access_table *table)
|
||||||
|
{
|
||||||
|
/* Check "no ranges" first */
|
||||||
|
if (regmap_reg_in_ranges(reg, table->no_ranges, table->n_no_ranges))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* In case zero "yes ranges" are supplied, any reg is OK */
|
||||||
|
if (!table->n_yes_ranges)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return regmap_reg_in_ranges(reg, table->yes_ranges,
|
||||||
|
table->n_yes_ranges);
|
||||||
|
}
|
||||||
|
|
||||||
bool regmap_writeable(struct regmap *map, unsigned int reg)
|
bool regmap_writeable(struct regmap *map, unsigned int reg)
|
||||||
{
|
{
|
||||||
if (map->max_register && reg > map->max_register)
|
if (map->max_register && reg > map->max_register)
|
||||||
@ -42,6 +72,9 @@ bool regmap_writeable(struct regmap *map, unsigned int reg)
|
|||||||
if (map->writeable_reg)
|
if (map->writeable_reg)
|
||||||
return map->writeable_reg(map->dev, reg);
|
return map->writeable_reg(map->dev, reg);
|
||||||
|
|
||||||
|
if (map->wr_table)
|
||||||
|
return _regmap_check_range_table(map, reg, map->wr_table);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +89,9 @@ bool regmap_readable(struct regmap *map, unsigned int reg)
|
|||||||
if (map->readable_reg)
|
if (map->readable_reg)
|
||||||
return map->readable_reg(map->dev, reg);
|
return map->readable_reg(map->dev, reg);
|
||||||
|
|
||||||
|
if (map->rd_table)
|
||||||
|
return _regmap_check_range_table(map, reg, map->rd_table);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +103,9 @@ bool regmap_volatile(struct regmap *map, unsigned int reg)
|
|||||||
if (map->volatile_reg)
|
if (map->volatile_reg)
|
||||||
return map->volatile_reg(map->dev, reg);
|
return map->volatile_reg(map->dev, reg);
|
||||||
|
|
||||||
|
if (map->volatile_table)
|
||||||
|
return _regmap_check_range_table(map, reg, map->volatile_table);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +117,9 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
|
|||||||
if (map->precious_reg)
|
if (map->precious_reg)
|
||||||
return map->precious_reg(map->dev, reg);
|
return map->precious_reg(map->dev, reg);
|
||||||
|
|
||||||
|
if (map->precious_table)
|
||||||
|
return _regmap_check_range_table(map, reg, map->precious_table);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,6 +412,10 @@ struct regmap *regmap_init(struct device *dev,
|
|||||||
map->bus = bus;
|
map->bus = bus;
|
||||||
map->bus_context = bus_context;
|
map->bus_context = bus_context;
|
||||||
map->max_register = config->max_register;
|
map->max_register = config->max_register;
|
||||||
|
map->wr_table = config->wr_table;
|
||||||
|
map->rd_table = config->rd_table;
|
||||||
|
map->volatile_table = config->volatile_table;
|
||||||
|
map->precious_table = config->precious_table;
|
||||||
map->writeable_reg = config->writeable_reg;
|
map->writeable_reg = config->writeable_reg;
|
||||||
map->readable_reg = config->readable_reg;
|
map->readable_reg = config->readable_reg;
|
||||||
map->volatile_reg = config->volatile_reg;
|
map->volatile_reg = config->volatile_reg;
|
||||||
|
@ -54,6 +54,36 @@ enum regmap_endian {
|
|||||||
REGMAP_ENDIAN_NATIVE,
|
REGMAP_ENDIAN_NATIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A register range, used for access related checks
|
||||||
|
* (readable/writeable/volatile/precious checks)
|
||||||
|
*
|
||||||
|
* @range_min: address of first register
|
||||||
|
* @range_max: address of last register
|
||||||
|
*/
|
||||||
|
struct regmap_range {
|
||||||
|
unsigned int range_min;
|
||||||
|
unsigned int range_max;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A table of ranges including some yes ranges and some no ranges.
|
||||||
|
* If a register belongs to a no_range, the corresponding check function
|
||||||
|
* will return false. If a register belongs to a yes range, the corresponding
|
||||||
|
* check function will return true. "no_ranges" are searched first.
|
||||||
|
*
|
||||||
|
* @yes_ranges : pointer to an array of regmap ranges used as "yes ranges"
|
||||||
|
* @n_yes_ranges: size of the above array
|
||||||
|
* @no_ranges: pointer to an array of regmap ranges used as "no ranges"
|
||||||
|
* @n_no_ranges: size of the above array
|
||||||
|
*/
|
||||||
|
struct regmap_access_table {
|
||||||
|
const struct regmap_range *yes_ranges;
|
||||||
|
unsigned int n_yes_ranges;
|
||||||
|
const struct regmap_range *no_ranges;
|
||||||
|
unsigned int n_no_ranges;
|
||||||
|
};
|
||||||
|
|
||||||
typedef void (*regmap_lock)(void *);
|
typedef void (*regmap_lock)(void *);
|
||||||
typedef void (*regmap_unlock)(void *);
|
typedef void (*regmap_unlock)(void *);
|
||||||
|
|
||||||
@ -71,22 +101,39 @@ typedef void (*regmap_unlock)(void *);
|
|||||||
* @val_bits: Number of bits in a register value, mandatory.
|
* @val_bits: Number of bits in a register value, mandatory.
|
||||||
*
|
*
|
||||||
* @writeable_reg: Optional callback returning true if the register
|
* @writeable_reg: Optional callback returning true if the register
|
||||||
* can be written to.
|
* can be written to. If this field is NULL but wr_table
|
||||||
|
* (see below) is not, the check is performed on such table
|
||||||
|
* (a register is writeable if it belongs to one of the ranges
|
||||||
|
* specified by wr_table).
|
||||||
* @readable_reg: Optional callback returning true if the register
|
* @readable_reg: Optional callback returning true if the register
|
||||||
* can be read from.
|
* can be read from. If this field is NULL but rd_table
|
||||||
|
* (see below) is not, the check is performed on such table
|
||||||
|
* (a register is readable if it belongs to one of the ranges
|
||||||
|
* specified by rd_table).
|
||||||
* @volatile_reg: Optional callback returning true if the register
|
* @volatile_reg: Optional callback returning true if the register
|
||||||
* value can't be cached.
|
* value can't be cached. If this field is NULL but
|
||||||
|
* volatile_table (see below) is not, the check is performed on
|
||||||
|
* such table (a register is volatile if it belongs to one of
|
||||||
|
* the ranges specified by volatile_table).
|
||||||
* @precious_reg: Optional callback returning true if the rgister
|
* @precious_reg: Optional callback returning true if the rgister
|
||||||
* should not be read outside of a call from the driver
|
* should not be read outside of a call from the driver
|
||||||
* (eg, a clear on read interrupt status register).
|
* (eg, a clear on read interrupt status register). If this
|
||||||
* @lock: Optional lock callback (overrides regmap's default lock
|
* field is NULL but precious_table (see below) is not, the
|
||||||
* function, based on spinlock or mutex).
|
* check is performed on such table (a register is precious if
|
||||||
* @unlock: As above for unlocking.
|
* it belongs to one of the ranges specified by precious_table).
|
||||||
* @lock_arg: this field is passed as the only argument of lock/unlock
|
* @lock: Optional lock callback (overrides regmap's default lock
|
||||||
* functions (ignored in case regular lock/unlock functions
|
* function, based on spinlock or mutex).
|
||||||
* are not overridden).
|
* @unlock: As above for unlocking.
|
||||||
|
* @lock_arg: this field is passed as the only argument of lock/unlock
|
||||||
|
* functions (ignored in case regular lock/unlock functions
|
||||||
|
* are not overridden).
|
||||||
*
|
*
|
||||||
* @max_register: Optional, specifies the maximum valid register index.
|
* @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.
|
||||||
|
* @rd_table: As above, for read access.
|
||||||
|
* @volatile_table: As above, for volatile registers.
|
||||||
|
* @precious_table: As above, for precious registers.
|
||||||
* @reg_defaults: Power on reset values for registers (for use with
|
* @reg_defaults: Power on reset values for registers (for use with
|
||||||
* register cache support).
|
* register cache support).
|
||||||
* @num_reg_defaults: Number of elements in reg_defaults.
|
* @num_reg_defaults: Number of elements in reg_defaults.
|
||||||
@ -131,6 +178,10 @@ struct regmap_config {
|
|||||||
void *lock_arg;
|
void *lock_arg;
|
||||||
|
|
||||||
unsigned int max_register;
|
unsigned int max_register;
|
||||||
|
const struct regmap_access_table *wr_table;
|
||||||
|
const struct regmap_access_table *rd_table;
|
||||||
|
const struct regmap_access_table *volatile_table;
|
||||||
|
const struct regmap_access_table *precious_table;
|
||||||
const struct reg_default *reg_defaults;
|
const struct reg_default *reg_defaults;
|
||||||
unsigned int num_reg_defaults;
|
unsigned int num_reg_defaults;
|
||||||
enum regcache_type cache_type;
|
enum regcache_type cache_type;
|
||||||
@ -281,6 +332,16 @@ void regcache_mark_dirty(struct regmap *map);
|
|||||||
int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
||||||
int num_regs);
|
int num_regs);
|
||||||
|
|
||||||
|
static inline bool regmap_reg_in_range(unsigned int reg,
|
||||||
|
const struct regmap_range *range)
|
||||||
|
{
|
||||||
|
return reg >= range->range_min && reg <= range->range_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool regmap_reg_in_ranges(unsigned int reg,
|
||||||
|
const struct regmap_range *ranges,
|
||||||
|
unsigned int nranges);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description of an IRQ for the generic regmap irq_chip.
|
* Description of an IRQ for the generic regmap irq_chip.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user