[PATCH v2 1/2] regmap: Add support for device specific write and read flag masks.

September 05th, 2011 - 02:50 pm ET by Lars-Peter Clausen | Report spam
Some buses like SPI have no standard notation of read or write operations.
The general scheme here is to set or clear specific bits in the register
address to indicate whether the operation is a read or write. We already
support having a read flag mask per bus, but as there is no standard
the bits which need to be set or cleared differ between devices and vendors,
thus we need a mechanism to specify them per device.

This patch adds two new entries to the regmap_config struct, read_flag_mask and
write_flag_mask. These will be or'ed onto the top byte when doing a read or
write operation. If both masks are empty the device will fallback to the
regmap_bus masks.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>

No changes since v1

drivers/base/regmap/internal.h | 3 +++
drivers/base/regmap/regmap.c | 15 ++++++++++++
include/linux/regmap.h | 9 +++++++++
3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 5ab3fef..7e14d5a 100644
a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -46,6 +46,9 @@ struct regmap {
bool (*readable_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);
+
+ u8 read_flag_mask;
+ u8 write_flag_mask;
};

bool regmap_writeable(struct regmap *map, unsigned int reg);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index fa2bd89..8ecf8bf 100644
a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -147,6 +147,13 @@ struct regmap *regmap_init(struct device *dev,
map->volatile_reg = config->volatile_reg;
map->precious_reg = config->precious_reg;

+ 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 {
+ map->read_flag_mask = bus->read_flag_mask;
+ }
+
switch (config->reg_bits) {
case 4:
switch (config->val_bits) {
@@ -229,6 +236,7 @@ EXPORT_SYMBOL_GPL(regmap_exit);
static int _regmap_raw_write(struct regmap *map, unsigned int reg,
const void *val, size_t val_len)
{
+ u8 *u8 = map->work_buf;
void *buf;
int ret = -ENOTSUPP;
size_t len;
@@ -242,6 +250,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,

map->format.format_reg(map->work_buf, reg);

+ u8[0] |= map->write_flag_mask;
+
trace_regmap_hw_write_start(map->dev, reg,
val_len / map->format.val_bytes);

@@ -369,13 +379,12 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
map->format.format_reg(map->work_buf, reg);

/*
- * Some buses flag reads by setting the high bits in the
+ * Some buses or devices flag reads by setting the high bits in the
* register addresss; since it's always the high bits for all
* current formats we can do this here rather than in
* formatting. This may break if we get interesting formats.
*/
- if (map->bus->read_flag_mask)
- u8[0] |= map->bus->read_flag_mask;
+ u8[0] |= map->read_flag_mask;

trace_regmap_hw_read_start(map->dev, reg,
val_len / map->format.val_bytes);
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 449e264..f0b8d47 100644
a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -53,6 +53,12 @@ struct reg_default {
* @reg_defaults: Power on reset values for registers (for use with
* register cache support).
* @num_reg_defaults: Number of elements in reg_defaults.
+ *
+ * @read_flag_mask: Mask to be set in the top byte of the register when doing
+ * a read.
+ * @write_flag_mask: Mask to be set in the top byte of the register when doing
+ * a write. If both read_flag_mask and write_flag_mask are
+ * empty the regmap_bus default masks are used.
*/
struct regmap_config {
int reg_bits;
@@ -66,6 +72,9 @@ struct regmap_config {
unsigned int max_register;
struct reg_default *reg_defaults;
int num_reg_defaults;
+
+ u8 read_flag_mask;
+ u8 write_flag_mask;
};

typedef int (*regmap_hw_write)(struct device *dev, const void *data,
1.7.2.5

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
email Follow the discussionReplies 1 replyReplies Make a reply

Replies

#1 Mark Brown
September 05th, 2011 - 06:10 pm ET | Report spam
On Mon, Sep 05, 2011 at 08:46:32PM +0200, Lars-Peter Clausen wrote:
Some buses like SPI have no standard notation of read or write operations.
The general scheme here is to set or clear specific bits in the register
address to indicate whether the operation is a read or write. We already
support having a read flag mask per bus, but as there is no standard
the bits which need to be set or cleared differ between devices and vendors,
thus we need a mechanism to specify them per device.



So, I tried to apply this to my topic/interface branch (which is where
I'm keeping stuff for merge into other trees) but that won't fly due to
the internal.h change. What I might do to resolve the merge issues is
to make a commit with the new regmap.h changes alone. This won't help
in terms of actually running things but it'll keep things buildable
which is more achievable.

Anyway, thanks for doing this - there's a bunch of other devices that
need this.
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Similar topics