Merge remote-tracking branch 'regmap/topic/dt-endian' into regmap-next
This commit is contained in:
commit
45942c310d
|
@ -0,0 +1,47 @@
|
|||
Device-Tree binding for regmap
|
||||
|
||||
The endianness mode of CPU & Device scenarios:
|
||||
Index Device Endianness properties
|
||||
---------------------------------------------------
|
||||
1 BE 'big-endian'
|
||||
2 LE 'little-endian'
|
||||
|
||||
For one device driver, which will run in different scenarios above
|
||||
on different SoCs using the devicetree, we need one way to simplify
|
||||
this.
|
||||
|
||||
Required properties:
|
||||
- {big,little}-endian: these are boolean properties, if absent
|
||||
meaning that the CPU and the Device are in the same endianness mode,
|
||||
these properties are for register values and all the buffers only.
|
||||
|
||||
Examples:
|
||||
Scenario 1 : CPU in LE mode & device in LE mode.
|
||||
dev: dev@40031000 {
|
||||
compatible = "name";
|
||||
reg = <0x40031000 0x1000>;
|
||||
...
|
||||
};
|
||||
|
||||
Scenario 2 : CPU in LE mode & device in BE mode.
|
||||
dev: dev@40031000 {
|
||||
compatible = "name";
|
||||
reg = <0x40031000 0x1000>;
|
||||
...
|
||||
big-endian;
|
||||
};
|
||||
|
||||
Scenario 3 : CPU in BE mode & device in BE mode.
|
||||
dev: dev@40031000 {
|
||||
compatible = "name";
|
||||
reg = <0x40031000 0x1000>;
|
||||
...
|
||||
};
|
||||
|
||||
Scenario 4 : CPU in BE mode & device in LE mode.
|
||||
dev: dev@40031000 {
|
||||
compatible = "name";
|
||||
reg = <0x40031000 0x1000>;
|
||||
...
|
||||
little-endian;
|
||||
};
|
|
@ -168,6 +168,8 @@ static struct regmap_bus regmap_i2c = {
|
|||
.write = regmap_i2c_write,
|
||||
.gather_write = regmap_i2c_gather_write,
|
||||
.read = regmap_i2c_read,
|
||||
.reg_format_endian_default = REGMAP_ENDIAN_BIG,
|
||||
.val_format_endian_default = REGMAP_ENDIAN_BIG,
|
||||
};
|
||||
|
||||
static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
|
||||
|
|
|
@ -109,6 +109,8 @@ static struct regmap_bus regmap_spi = {
|
|||
.async_alloc = regmap_spi_async_alloc,
|
||||
.read = regmap_spi_read,
|
||||
.read_flag_mask = 0x80,
|
||||
.reg_format_endian_default = REGMAP_ENDIAN_BIG,
|
||||
.val_format_endian_default = REGMAP_ENDIAN_BIG,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
@ -448,6 +449,71 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_attach_dev);
|
||||
|
||||
static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
|
||||
const struct regmap_config *config)
|
||||
{
|
||||
enum regmap_endian endian;
|
||||
|
||||
/* Retrieve the endianness specification from the regmap config */
|
||||
endian = config->reg_format_endian;
|
||||
|
||||
/* If the regmap config specified a non-default value, use that */
|
||||
if (endian != REGMAP_ENDIAN_DEFAULT)
|
||||
return endian;
|
||||
|
||||
/* Retrieve the endianness specification from the bus config */
|
||||
if (bus && bus->reg_format_endian_default)
|
||||
endian = bus->reg_format_endian_default;
|
||||
|
||||
/* If the bus specified a non-default value, use that */
|
||||
if (endian != REGMAP_ENDIAN_DEFAULT)
|
||||
return endian;
|
||||
|
||||
/* Use this if no other value was found */
|
||||
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)
|
||||
{
|
||||
struct device_node *np;
|
||||
enum regmap_endian endian;
|
||||
|
||||
/* Retrieve the endianness specification from the regmap config */
|
||||
endian = config->val_format_endian;
|
||||
|
||||
/* If the regmap config specified a non-default value, use that */
|
||||
if (endian != REGMAP_ENDIAN_DEFAULT)
|
||||
return endian;
|
||||
|
||||
/* If the dev and dev->of_node exist try to get endianness from DT */
|
||||
if (dev && dev->of_node) {
|
||||
np = dev->of_node;
|
||||
|
||||
/* Parse the device's DT node for an endianness specification */
|
||||
if (of_property_read_bool(np, "big-endian"))
|
||||
endian = REGMAP_ENDIAN_BIG;
|
||||
else if (of_property_read_bool(np, "little-endian"))
|
||||
endian = REGMAP_ENDIAN_LITTLE;
|
||||
|
||||
/* If the endianness was specified in DT, use that */
|
||||
if (endian != REGMAP_ENDIAN_DEFAULT)
|
||||
return endian;
|
||||
}
|
||||
|
||||
/* Retrieve the endianness specification from the bus config */
|
||||
if (bus && bus->val_format_endian_default)
|
||||
endian = bus->val_format_endian_default;
|
||||
|
||||
/* If the bus specified a non-default value, use that */
|
||||
if (endian != REGMAP_ENDIAN_DEFAULT)
|
||||
return endian;
|
||||
|
||||
/* Use this if no other value was found */
|
||||
return REGMAP_ENDIAN_BIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* regmap_init(): Initialise register map
|
||||
*
|
||||
|
@ -551,17 +617,8 @@ struct regmap *regmap_init(struct device *dev,
|
|||
map->reg_read = _regmap_bus_read;
|
||||
}
|
||||
|
||||
reg_endian = config->reg_format_endian;
|
||||
if (reg_endian == REGMAP_ENDIAN_DEFAULT)
|
||||
reg_endian = bus->reg_format_endian_default;
|
||||
if (reg_endian == REGMAP_ENDIAN_DEFAULT)
|
||||
reg_endian = REGMAP_ENDIAN_BIG;
|
||||
|
||||
val_endian = config->val_format_endian;
|
||||
if (val_endian == REGMAP_ENDIAN_DEFAULT)
|
||||
val_endian = bus->val_format_endian_default;
|
||||
if (val_endian == REGMAP_ENDIAN_DEFAULT)
|
||||
val_endian = REGMAP_ENDIAN_BIG;
|
||||
reg_endian = regmap_get_reg_endian(bus, config);
|
||||
val_endian = regmap_get_val_endian(dev, bus, config);
|
||||
|
||||
switch (config->reg_bits + map->reg_shift) {
|
||||
case 2:
|
||||
|
|
Loading…
Reference in New Issue