aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-12-10 22:39:32 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-12-10 22:39:32 -0500
commit8e24a6e696ebdc44513357ac00b6ee18f54e69f5 (patch)
tree82cc7ac9259a9f20159f9265aca52533b1cb3ca8
parentdb760fbecd3d609098ef4121d7988ff2a5db15d1 (diff)
parent76aad392f75e6ce5be3f106554e16f7ff96543e5 (diff)
Merge remote-tracking branch 'regmap/topic/table' into regmap-next
-rw-r--r--drivers/base/regmap/internal.h4
-rw-r--r--drivers/base/regmap/regmap.c46
-rw-r--r--include/linux/regmap.h83
3 files changed, 122 insertions, 11 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 0fadeba64ce0..401d1919635a 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -69,6 +69,10 @@ struct regmap {
69 bool (*readable_reg)(struct device *dev, unsigned int reg); 69 bool (*readable_reg)(struct device *dev, unsigned int reg);
70 bool (*volatile_reg)(struct device *dev, unsigned int reg); 70 bool (*volatile_reg)(struct device *dev, unsigned int reg);
71 bool (*precious_reg)(struct device *dev, unsigned int reg); 71 bool (*precious_reg)(struct device *dev, unsigned int reg);
72 const struct regmap_access_table *wr_table;
73 const struct regmap_access_table *rd_table;
74 const struct regmap_access_table *volatile_table;
75 const struct regmap_access_table *precious_table;
72 76
73 u8 read_flag_mask; 77 u8 read_flag_mask;
74 u8 write_flag_mask; 78 u8 write_flag_mask;
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 64eb8350a074..96f7e8523ee8 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -34,6 +34,36 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
34 unsigned int mask, unsigned int val, 34 unsigned int mask, unsigned int val,
35 bool *change); 35 bool *change);
36 36
37bool regmap_reg_in_ranges(unsigned int reg,
38 const struct regmap_range *ranges,
39 unsigned int nranges)
40{
41 const struct regmap_range *r;
42 int i;
43
44 for (i = 0, r = ranges; i < nranges; i++, r++)
45 if (regmap_reg_in_range(reg, r))
46 return true;
47 return false;
48}
49EXPORT_SYMBOL_GPL(regmap_reg_in_ranges);
50
51static bool _regmap_check_range_table(struct regmap *map,
52 unsigned int reg,
53 const struct regmap_access_table *table)
54{
55 /* Check "no ranges" first */
56 if (regmap_reg_in_ranges(reg, table->no_ranges, table->n_no_ranges))
57 return false;
58
59 /* In case zero "yes ranges" are supplied, any reg is OK */
60 if (!table->n_yes_ranges)
61 return true;
62
63 return regmap_reg_in_ranges(reg, table->yes_ranges,
64 table->n_yes_ranges);
65}
66
37bool regmap_writeable(struct regmap *map, unsigned int reg) 67bool regmap_writeable(struct regmap *map, unsigned int reg)
38{ 68{
39 if (map->max_register && reg > map->max_register) 69 if (map->max_register && reg > map->max_register)
@@ -42,6 +72,9 @@ bool regmap_writeable(struct regmap *map, unsigned int reg)
42 if (map->writeable_reg) 72 if (map->writeable_reg)
43 return map->writeable_reg(map->dev, reg); 73 return map->writeable_reg(map->dev, reg);
44 74
75 if (map->wr_table)
76 return _regmap_check_range_table(map, reg, map->wr_table);
77
45 return true; 78 return true;
46} 79}
47 80
@@ -56,6 +89,9 @@ bool regmap_readable(struct regmap *map, unsigned int reg)
56 if (map->readable_reg) 89 if (map->readable_reg)
57 return map->readable_reg(map->dev, reg); 90 return map->readable_reg(map->dev, reg);
58 91
92 if (map->rd_table)
93 return _regmap_check_range_table(map, reg, map->rd_table);
94
59 return true; 95 return true;
60} 96}
61 97
@@ -67,6 +103,9 @@ bool regmap_volatile(struct regmap *map, unsigned int reg)
67 if (map->volatile_reg) 103 if (map->volatile_reg)
68 return map->volatile_reg(map->dev, reg); 104 return map->volatile_reg(map->dev, reg);
69 105
106 if (map->volatile_table)
107 return _regmap_check_range_table(map, reg, map->volatile_table);
108
70 return true; 109 return true;
71} 110}
72 111
@@ -78,6 +117,9 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
78 if (map->precious_reg) 117 if (map->precious_reg)
79 return map->precious_reg(map->dev, reg); 118 return map->precious_reg(map->dev, reg);
80 119
120 if (map->precious_table)
121 return _regmap_check_range_table(map, reg, map->precious_table);
122
81 return false; 123 return false;
82} 124}
83 125
@@ -370,6 +412,10 @@ struct regmap *regmap_init(struct device *dev,
370 map->bus = bus; 412 map->bus = bus;
371 map->bus_context = bus_context; 413 map->bus_context = bus_context;
372 map->max_register = config->max_register; 414 map->max_register = config->max_register;
415 map->wr_table = config->wr_table;
416 map->rd_table = config->rd_table;
417 map->volatile_table = config->volatile_table;
418 map->precious_table = config->precious_table;
373 map->writeable_reg = config->writeable_reg; 419 map->writeable_reg = config->writeable_reg;
374 map->readable_reg = config->readable_reg; 420 map->readable_reg = config->readable_reg;
375 map->volatile_reg = config->volatile_reg; 421 map->volatile_reg = config->volatile_reg;
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index fedf7ba74590..b7e95bf942c9 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -54,6 +54,36 @@ enum regmap_endian {
54 REGMAP_ENDIAN_NATIVE, 54 REGMAP_ENDIAN_NATIVE,
55}; 55};
56 56
57/**
58 * A register range, used for access related checks
59 * (readable/writeable/volatile/precious checks)
60 *
61 * @range_min: address of first register
62 * @range_max: address of last register
63 */
64struct regmap_range {
65 unsigned int range_min;
66 unsigned int range_max;
67};
68
69/*
70 * A table of ranges including some yes ranges and some no ranges.
71 * If a register belongs to a no_range, the corresponding check function
72 * will return false. If a register belongs to a yes range, the corresponding
73 * check function will return true. "no_ranges" are searched first.
74 *
75 * @yes_ranges : pointer to an array of regmap ranges used as "yes ranges"
76 * @n_yes_ranges: size of the above array
77 * @no_ranges: pointer to an array of regmap ranges used as "no ranges"
78 * @n_no_ranges: size of the above array
79 */
80struct regmap_access_table {
81 const struct regmap_range *yes_ranges;
82 unsigned int n_yes_ranges;
83 const struct regmap_range *no_ranges;
84 unsigned int n_no_ranges;
85};
86
57typedef void (*regmap_lock)(void *); 87typedef void (*regmap_lock)(void *);
58typedef void (*regmap_unlock)(void *); 88typedef void (*regmap_unlock)(void *);
59 89
@@ -71,22 +101,39 @@ typedef void (*regmap_unlock)(void *);
71 * @val_bits: Number of bits in a register value, mandatory. 101 * @val_bits: Number of bits in a register value, mandatory.
72 * 102 *
73 * @writeable_reg: Optional callback returning true if the register 103 * @writeable_reg: Optional callback returning true if the register
74 * can be written to. 104 * can be written to. If this field is NULL but wr_table
105 * (see below) is not, the check is performed on such table
106 * (a register is writeable if it belongs to one of the ranges
107 * specified by wr_table).
75 * @readable_reg: Optional callback returning true if the register 108 * @readable_reg: Optional callback returning true if the register
76 * can be read from. 109 * can be read from. If this field is NULL but rd_table
110 * (see below) is not, the check is performed on such table
111 * (a register is readable if it belongs to one of the ranges
112 * specified by rd_table).
77 * @volatile_reg: Optional callback returning true if the register 113 * @volatile_reg: Optional callback returning true if the register
78 * value can't be cached. 114 * value can't be cached. If this field is NULL but
115 * volatile_table (see below) is not, the check is performed on
116 * such table (a register is volatile if it belongs to one of
117 * the ranges specified by volatile_table).
79 * @precious_reg: Optional callback returning true if the rgister 118 * @precious_reg: Optional callback returning true if the rgister
80 * should not be read outside of a call from the driver 119 * should not be read outside of a call from the driver
81 * (eg, a clear on read interrupt status register). 120 * (eg, a clear on read interrupt status register). If this
82 * @lock: Optional lock callback (overrides regmap's default lock 121 * field is NULL but precious_table (see below) is not, the
83 * function, based on spinlock or mutex). 122 * check is performed on such table (a register is precious if
84 * @unlock: As above for unlocking. 123 * it belongs to one of the ranges specified by precious_table).
85 * @lock_arg: this field is passed as the only argument of lock/unlock 124 * @lock: Optional lock callback (overrides regmap's default lock
86 * functions (ignored in case regular lock/unlock functions 125 * function, based on spinlock or mutex).
87 * are not overridden). 126 * @unlock: As above for unlocking.
127 * @lock_arg: this field is passed as the only argument of lock/unlock
128 * functions (ignored in case regular lock/unlock functions
129 * are not overridden).
88 * 130 *
89 * @max_register: Optional, specifies the maximum valid register index. 131 * @max_register: Optional, specifies the maximum valid register index.
132 * @wr_table: Optional, points to a struct regmap_access_table specifying
133 * valid ranges for write access.
134 * @rd_table: As above, for read access.
135 * @volatile_table: As above, for volatile registers.
136 * @precious_table: As above, for precious registers.
90 * @reg_defaults: Power on reset values for registers (for use with 137 * @reg_defaults: Power on reset values for registers (for use with
91 * register cache support). 138 * register cache support).
92 * @num_reg_defaults: Number of elements in reg_defaults. 139 * @num_reg_defaults: Number of elements in reg_defaults.
@@ -131,6 +178,10 @@ struct regmap_config {
131 void *lock_arg; 178 void *lock_arg;
132 179
133 unsigned int max_register; 180 unsigned int max_register;
181 const struct regmap_access_table *wr_table;
182 const struct regmap_access_table *rd_table;
183 const struct regmap_access_table *volatile_table;
184 const struct regmap_access_table *precious_table;
134 const struct reg_default *reg_defaults; 185 const struct reg_default *reg_defaults;
135 unsigned int num_reg_defaults; 186 unsigned int num_reg_defaults;
136 enum regcache_type cache_type; 187 enum regcache_type cache_type;
@@ -281,6 +332,16 @@ void regcache_mark_dirty(struct regmap *map);
281int regmap_register_patch(struct regmap *map, const struct reg_default *regs, 332int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
282 int num_regs); 333 int num_regs);
283 334
335static inline bool regmap_reg_in_range(unsigned int reg,
336 const struct regmap_range *range)
337{
338 return reg >= range->range_min && reg <= range->range_max;
339}
340
341bool regmap_reg_in_ranges(unsigned int reg,
342 const struct regmap_range *ranges,
343 unsigned int nranges);
344
284/** 345/**
285 * Description of an IRQ for the generic regmap irq_chip. 346 * Description of an IRQ for the generic regmap irq_chip.
286 * 347 *