regmap: Updates for v3.11
A small but useful set of regmap updates this time around: - An abstraction for bitfields within a register map contributed by Srinivas Kandagatla, allowing drivers to cope more easily when hardware designers randomly move things about (mainly when talking to things like system controllers). - Changes from Lars-Peter Clausen to allow the MMIO regmap to be used from hard IRQ context. - Small improvements to the cache infrastructure and performance, including a default cache sync operation so now all regmaps can sync easily. There's also a pinctrl driver making use of the new bitfield API, merged here for dependency reasons. There will be a simple add/add conflict with the pinctrl tree as a result. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJR0BkmAAoJELSic+t+oim94wgP/A+a0uJNxkQ3VK2myUU42VzA LkiSgmpV/IsywyMJjV+/WgSPXv5BALjWdoHqaPGxEzbVTrQdxTVWhrlPsFAu7rLo dQXoAXckvyhaw+GlJNpUkpIrNV3qxZN9eT8/Lm16pehXzllZif7CynJk6F5NQgMw 32HKuNFJxig+NMDzbeID1aSTg5yCsU+TCB40J7naYDAGIBXwNsXwGmVwoTJi6513 xWEJ8KvQ5F2C5PCUass+9Cozil/H95V1Vvei5qyo7aVG1Z2SF4ueC8sRZgULvTr/ wpPt/ia8TnjQcjYvnFVWyiiCGDmmYB+CQHxtIjsLVYoaBb2FsLEVfscYD+84+EAz mQqEKxLIPfYvzZmU8zxcdXzDkD+Ztm0T8HJWrKwIWfBiKgrSk6R2kegFOrCrqmLX cVHW3RXVZM3oW8G9T5FGR5fzh9acnAvvTKstSPnpMXTRLKozPG6G61+FtjDQNvxI 0IGgNnkZCxGFmVLAxzX/Z4WmuwARO+dSbY2t92qlOhfRLVJ8VR5WVu+ECDYDSBUD U0EhXfmu2UJdClY2T+lw3TRo3F7hKHx5+C6cS6pNZC43lKtGWu8qClFmdJ+Y2Pzp 4yRUvKXjfnyuRNSYaIRcjxJQ7dPVfxsUz3w9cak4V/Gi2u/1cbbTjS+Wob1+jdEu 9ldwQ9d3gMMVWR5yb/Z4 =8WLH -----END PGP SIGNATURE----- Merge tag 'regmap-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap Pull regmap updates from Mark Brown: "A small but useful set of regmap updates this time around: - An abstraction for bitfields within a register map contributed by Srinivas Kandagatla, allowing drivers to cope more easily when hardware designers randomly move things about (mainly when talking to things like system controllers). - Changes from Lars-Peter Clausen to allow the MMIO regmap to be used from hard IRQ context. - Small improvements to the cache infrastructure and performance, including a default cache sync operation so now all regmaps can sync easily. There's also a pinctrl driver making use of the new bitfield API, merged here for dependency reasons. There will be a simple add/add conflict with the pinctrl tree as a result." * tag 'regmap-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: pinctrl: st: Remove unnecessary use of of_match_ptr macro pinctrl: st: fix return value check pinctrl: st: Add pinctrl and pinconf support. regmap: debugfs: Suppress cache for partial register files regmap: Add regmap_field APIs regmap: core: Cache all registers by default when cache is enabled regmap: Implemented default cache sync operation regmap: Make regmap-mmio usable from atomic contexts regmap: regcache: Fixup locking for custom lock callbacks regmap: debugfs: Fix return from regmap_debugfs_get_dump_start regmap: debugfs: Don't mark lockdep as broken due to debugfs write regmap: rbtree: Use range information to allocate nodes regmap: rbtree: Factor out node allocation regmap: Make regmap_check_range_table() a public API regmap: Add support for discarding parts of the register cache
This commit is contained in:
commit
a6e6d863cf
|
@ -0,0 +1,110 @@
|
|||
*ST pin controller.
|
||||
|
||||
Each multi-function pin is controlled, driven and routed through the
|
||||
PIO multiplexing block. Each pin supports GPIO functionality (ALT0)
|
||||
and multiple alternate functions(ALT1 - ALTx) that directly connect
|
||||
the pin to different hardware blocks.
|
||||
|
||||
When a pin is in GPIO mode, Output Enable (OE), Open Drain(OD), and
|
||||
Pull Up (PU) are driven by the related PIO block.
|
||||
|
||||
ST pinctrl driver controls PIO multiplexing block and also interacts with
|
||||
gpio driver to configure a pin.
|
||||
|
||||
Required properties: (PIO multiplexing block)
|
||||
- compatible : should be "st,<SOC>-<pio-block>-pinctrl"
|
||||
like st,stih415-sbc-pinctrl, st,stih415-front-pinctrl and so on.
|
||||
- gpio-controller : Indicates this device is a GPIO controller
|
||||
- #gpio-cells : Should be one. The first cell is the pin number.
|
||||
- st,retime-pin-mask : Should be mask to specify which pins can be retimed.
|
||||
If the property is not present, it is assumed that all the pins in the
|
||||
bank are capable of retiming. Retiming is mainly used to improve the
|
||||
IO timing margins of external synchronous interfaces.
|
||||
- st,bank-name : Should be a name string for this bank as
|
||||
specified in datasheet.
|
||||
- st,syscfg : Should be a phandle of the syscfg node.
|
||||
|
||||
Example:
|
||||
pin-controller-sbc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "st,stih415-sbc-pinctrl";
|
||||
st,syscfg = <&syscfg_sbc>;
|
||||
ranges = <0 0xfe610000 0x5000>;
|
||||
PIO0: gpio@fe610000 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <1>;
|
||||
reg = <0 0x100>;
|
||||
st,bank-name = "PIO0";
|
||||
};
|
||||
...
|
||||
pin-functions nodes follow...
|
||||
};
|
||||
|
||||
|
||||
Contents of function subnode node:
|
||||
----------------------
|
||||
Required properties for pin configuration node:
|
||||
- st,pins : Child node with list of pins with configuration.
|
||||
|
||||
Below is the format of how each pin conf should look like.
|
||||
|
||||
<bank offset mux mode rt_type rt_delay rt_clk>
|
||||
|
||||
Every PIO is represented with 4-7 parameters depending on retime configuration.
|
||||
Each parameter is explained as below.
|
||||
|
||||
-bank : Should be bank phandle to which this PIO belongs.
|
||||
-offset : Offset in the PIO bank.
|
||||
-mux : Should be alternate function number associated this pin.
|
||||
Use same numbers from datasheet.
|
||||
-mode :pin configuration is selected from one of the below values.
|
||||
IN
|
||||
IN_PU
|
||||
OUT
|
||||
BIDIR
|
||||
BIDIR_PU
|
||||
|
||||
-rt_type Retiming Configuration for the pin.
|
||||
Possible retime configuration are:
|
||||
|
||||
------- -------------
|
||||
value args
|
||||
------- -------------
|
||||
NICLK <delay> <clk>
|
||||
ICLK_IO <delay> <clk>
|
||||
BYPASS <delay>
|
||||
DE_IO <delay> <clk>
|
||||
SE_ICLK_IO <delay> <clk>
|
||||
SE_NICLK_IO <delay> <clk>
|
||||
|
||||
- delay is retime delay in pico seconds as mentioned in data sheet.
|
||||
|
||||
- rt_clk :clk to be use for retime.
|
||||
Possible values are:
|
||||
CLK_A
|
||||
CLK_B
|
||||
CLK_C
|
||||
CLK_D
|
||||
|
||||
Example of mmcclk pin which is a bi-direction pull pu with retime config
|
||||
as non inverted clock retimed with CLK_B and delay of 0 pico seconds:
|
||||
|
||||
pin-controller {
|
||||
...
|
||||
mmc0 {
|
||||
pinctrl_mmc: mmc {
|
||||
st,pins {
|
||||
mmcclk = <&PIO13 4 ALT4 BIDIR_PU NICLK 0 CLK_B>;
|
||||
...
|
||||
};
|
||||
};
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
sdhci0:sdhci@fe810000{
|
||||
...
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_mmc>;
|
||||
};
|
|
@ -52,6 +52,7 @@ struct regmap_async {
|
|||
struct regmap {
|
||||
struct mutex mutex;
|
||||
spinlock_t spinlock;
|
||||
unsigned long spinlock_flags;
|
||||
regmap_lock lock;
|
||||
regmap_unlock unlock;
|
||||
void *lock_arg; /* This is passed to lock/unlock functions */
|
||||
|
@ -148,6 +149,7 @@ struct regcache_ops {
|
|||
int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
|
||||
int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
|
||||
int (*sync)(struct regmap *map, unsigned int min, unsigned int max);
|
||||
int (*drop)(struct regmap *map, unsigned int min, unsigned int max);
|
||||
};
|
||||
|
||||
bool regmap_writeable(struct regmap *map, unsigned int reg);
|
||||
|
@ -174,6 +176,14 @@ struct regmap_range_node {
|
|||
unsigned int window_len;
|
||||
};
|
||||
|
||||
struct regmap_field {
|
||||
struct regmap *regmap;
|
||||
unsigned int mask;
|
||||
/* lsb */
|
||||
unsigned int shift;
|
||||
unsigned int reg;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern void regmap_debugfs_initcall(void);
|
||||
extern void regmap_debugfs_init(struct regmap *map, const char *name);
|
||||
|
|
|
@ -304,6 +304,48 @@ static int regcache_rbtree_insert_to_block(struct regmap *map,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct regcache_rbtree_node *
|
||||
regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg)
|
||||
{
|
||||
struct regcache_rbtree_node *rbnode;
|
||||
const struct regmap_range *range;
|
||||
int i;
|
||||
|
||||
rbnode = kzalloc(sizeof(*rbnode), GFP_KERNEL);
|
||||
if (!rbnode)
|
||||
return NULL;
|
||||
|
||||
/* If there is a read table then use it to guess at an allocation */
|
||||
if (map->rd_table) {
|
||||
for (i = 0; i < map->rd_table->n_yes_ranges; i++) {
|
||||
if (regmap_reg_in_range(reg,
|
||||
&map->rd_table->yes_ranges[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != map->rd_table->n_yes_ranges) {
|
||||
range = &map->rd_table->yes_ranges[i];
|
||||
rbnode->blklen = range->range_max - range->range_min
|
||||
+ 1;
|
||||
rbnode->base_reg = range->range_min;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rbnode->blklen) {
|
||||
rbnode->blklen = sizeof(*rbnode);
|
||||
rbnode->base_reg = reg;
|
||||
}
|
||||
|
||||
rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
|
||||
GFP_KERNEL);
|
||||
if (!rbnode->block) {
|
||||
kfree(rbnode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rbnode;
|
||||
}
|
||||
|
||||
static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
|
@ -354,23 +396,15 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
/* we did not manage to find a place to insert it in an existing
|
||||
* block so create a new rbnode with a single register in its block.
|
||||
* This block will get populated further if any other adjacent
|
||||
* registers get modified in the future.
|
||||
|
||||
/* We did not manage to find a place to insert it in
|
||||
* an existing block so create a new rbnode.
|
||||
*/
|
||||
rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
|
||||
rbnode = regcache_rbtree_node_alloc(map, reg);
|
||||
if (!rbnode)
|
||||
return -ENOMEM;
|
||||
rbnode->blklen = sizeof(*rbnode);
|
||||
rbnode->base_reg = reg;
|
||||
rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
|
||||
GFP_KERNEL);
|
||||
if (!rbnode->block) {
|
||||
kfree(rbnode);
|
||||
return -ENOMEM;
|
||||
}
|
||||
regcache_rbtree_set_register(map, rbnode, 0, value);
|
||||
regcache_rbtree_set_register(map, rbnode,
|
||||
reg - rbnode->base_reg, value);
|
||||
regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
|
||||
rbtree_ctx->cached_rbnode = rbnode;
|
||||
}
|
||||
|
|
|
@ -250,6 +250,38 @@ int regcache_write(struct regmap *map,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int regcache_default_sync(struct regmap *map, unsigned int min,
|
||||
unsigned int max)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
for (reg = min; reg <= max; reg++) {
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
if (regmap_volatile(map, reg))
|
||||
continue;
|
||||
|
||||
ret = regcache_read(map, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Is this the hardware default? If so skip. */
|
||||
ret = regcache_lookup_reg(map, reg);
|
||||
if (ret >= 0 && val == map->reg_defaults[ret].def)
|
||||
continue;
|
||||
|
||||
map->cache_bypass = 1;
|
||||
ret = _regmap_write(map, reg, val);
|
||||
map->cache_bypass = 0;
|
||||
if (ret)
|
||||
return ret;
|
||||
dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* regcache_sync: Sync the register cache with the hardware.
|
||||
*
|
||||
|
@ -268,7 +300,7 @@ int regcache_sync(struct regmap *map)
|
|||
const char *name;
|
||||
unsigned int bypass;
|
||||
|
||||
BUG_ON(!map->cache_ops || !map->cache_ops->sync);
|
||||
BUG_ON(!map->cache_ops);
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
/* Remember the initial bypass state */
|
||||
|
@ -297,7 +329,10 @@ int regcache_sync(struct regmap *map)
|
|||
}
|
||||
map->cache_bypass = 0;
|
||||
|
||||
ret = map->cache_ops->sync(map, 0, map->max_register);
|
||||
if (map->cache_ops->sync)
|
||||
ret = map->cache_ops->sync(map, 0, map->max_register);
|
||||
else
|
||||
ret = regcache_default_sync(map, 0, map->max_register);
|
||||
|
||||
if (ret == 0)
|
||||
map->cache_dirty = false;
|
||||
|
@ -331,7 +366,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
|
|||
const char *name;
|
||||
unsigned int bypass;
|
||||
|
||||
BUG_ON(!map->cache_ops || !map->cache_ops->sync);
|
||||
BUG_ON(!map->cache_ops);
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
|
||||
|
@ -346,7 +381,10 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
|
|||
if (!map->cache_dirty)
|
||||
goto out;
|
||||
|
||||
ret = map->cache_ops->sync(map, min, max);
|
||||
if (map->cache_ops->sync)
|
||||
ret = map->cache_ops->sync(map, min, max);
|
||||
else
|
||||
ret = regcache_default_sync(map, min, max);
|
||||
|
||||
out:
|
||||
trace_regcache_sync(map->dev, name, "stop region");
|
||||
|
@ -358,6 +396,43 @@ out:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regcache_sync_region);
|
||||
|
||||
/**
|
||||
* regcache_drop_region: Discard part of the register cache
|
||||
*
|
||||
* @map: map to operate on
|
||||
* @min: first register to discard
|
||||
* @max: last register to discard
|
||||
*
|
||||
* Discard part of the register cache.
|
||||
*
|
||||
* Return a negative value on failure, 0 on success.
|
||||
*/
|
||||
int regcache_drop_region(struct regmap *map, unsigned int min,
|
||||
unsigned int max)
|
||||
{
|
||||
unsigned int reg;
|
||||
int ret = 0;
|
||||
|
||||
if (!map->cache_present && !(map->cache_ops && map->cache_ops->drop))
|
||||
return -EINVAL;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
|
||||
trace_regcache_drop_region(map->dev, min, max);
|
||||
|
||||
if (map->cache_present)
|
||||
for (reg = min; reg < max + 1; reg++)
|
||||
clear_bit(reg, map->cache_present);
|
||||
|
||||
if (map->cache_ops && map->cache_ops->drop)
|
||||
ret = map->cache_ops->drop(map, min, max);
|
||||
|
||||
map->unlock(map->lock_arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regcache_drop_region);
|
||||
|
||||
/**
|
||||
* regcache_cache_only: Put a register map into cache only mode
|
||||
*
|
||||
|
|
|
@ -84,6 +84,10 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
|
|||
unsigned int fpos_offset;
|
||||
unsigned int reg_offset;
|
||||
|
||||
/* Suppress the cache if we're using a subrange */
|
||||
if (from)
|
||||
return from;
|
||||
|
||||
/*
|
||||
* If we don't have a cache build one so we don't have to do a
|
||||
* linear scan each time.
|
||||
|
@ -145,7 +149,7 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
|
|||
reg_offset = fpos_offset / map->debugfs_tot_len;
|
||||
*pos = c->min + (reg_offset * map->debugfs_tot_len);
|
||||
mutex_unlock(&map->cache_lock);
|
||||
return c->base_reg + reg_offset;
|
||||
return c->base_reg + (reg_offset * map->reg_stride);
|
||||
}
|
||||
|
||||
*pos = c->max;
|
||||
|
@ -281,7 +285,7 @@ static ssize_t regmap_map_write_file(struct file *file,
|
|||
return -EINVAL;
|
||||
|
||||
/* Userspace has been fiddling around behind the kernel's back */
|
||||
add_taint(TAINT_USER, LOCKDEP_NOW_UNRELIABLE);
|
||||
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||
|
||||
ret = regmap_write(map, reg, value);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -65,9 +65,8 @@ bool regmap_reg_in_ranges(unsigned int reg,
|
|||
}
|
||||
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)
|
||||
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))
|
||||
|
@ -80,6 +79,7 @@ static bool _regmap_check_range_table(struct regmap *map,
|
|||
return regmap_reg_in_ranges(reg, table->yes_ranges,
|
||||
table->n_yes_ranges);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_check_range_table);
|
||||
|
||||
bool regmap_writeable(struct regmap *map, unsigned int reg)
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ bool regmap_writeable(struct regmap *map, unsigned int reg)
|
|||
return map->writeable_reg(map->dev, reg);
|
||||
|
||||
if (map->wr_table)
|
||||
return _regmap_check_range_table(map, reg, map->wr_table);
|
||||
return regmap_check_range_table(map, reg, map->wr_table);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ bool regmap_readable(struct regmap *map, unsigned int reg)
|
|||
return map->readable_reg(map->dev, reg);
|
||||
|
||||
if (map->rd_table)
|
||||
return _regmap_check_range_table(map, reg, map->rd_table);
|
||||
return regmap_check_range_table(map, reg, map->rd_table);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -121,9 +121,12 @@ bool regmap_volatile(struct regmap *map, unsigned int reg)
|
|||
return map->volatile_reg(map->dev, reg);
|
||||
|
||||
if (map->volatile_table)
|
||||
return _regmap_check_range_table(map, reg, map->volatile_table);
|
||||
return regmap_check_range_table(map, reg, map->volatile_table);
|
||||
|
||||
return true;
|
||||
if (map->cache_ops)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool regmap_precious(struct regmap *map, unsigned int reg)
|
||||
|
@ -135,7 +138,7 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
|
|||
return map->precious_reg(map->dev, reg);
|
||||
|
||||
if (map->precious_table)
|
||||
return _regmap_check_range_table(map, reg, map->precious_table);
|
||||
return regmap_check_range_table(map, reg, map->precious_table);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -302,13 +305,16 @@ static void regmap_unlock_mutex(void *__map)
|
|||
static void regmap_lock_spinlock(void *__map)
|
||||
{
|
||||
struct regmap *map = __map;
|
||||
spin_lock(&map->spinlock);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&map->spinlock, flags);
|
||||
map->spinlock_flags = flags;
|
||||
}
|
||||
|
||||
static void regmap_unlock_spinlock(void *__map)
|
||||
{
|
||||
struct regmap *map = __map;
|
||||
spin_unlock(&map->spinlock);
|
||||
spin_unlock_irqrestore(&map->spinlock, map->spinlock_flags);
|
||||
}
|
||||
|
||||
static void dev_get_regmap_release(struct device *dev, void *res)
|
||||
|
@ -801,6 +807,95 @@ struct regmap *devm_regmap_init(struct device *dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(devm_regmap_init);
|
||||
|
||||
static void regmap_field_init(struct regmap_field *rm_field,
|
||||
struct regmap *regmap, struct reg_field reg_field)
|
||||
{
|
||||
int field_bits = reg_field.msb - reg_field.lsb + 1;
|
||||
rm_field->regmap = regmap;
|
||||
rm_field->reg = reg_field.reg;
|
||||
rm_field->shift = reg_field.lsb;
|
||||
rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_regmap_field_alloc(): Allocate and initialise a register field
|
||||
* in a register map.
|
||||
*
|
||||
* @dev: Device that will be interacted with
|
||||
* @regmap: regmap bank in which this register field is located.
|
||||
* @reg_field: Register field with in the bank.
|
||||
*
|
||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||
* to a struct regmap_field. The regmap_field will be automatically freed
|
||||
* by the device management code.
|
||||
*/
|
||||
struct regmap_field *devm_regmap_field_alloc(struct device *dev,
|
||||
struct regmap *regmap, struct reg_field reg_field)
|
||||
{
|
||||
struct regmap_field *rm_field = devm_kzalloc(dev,
|
||||
sizeof(*rm_field), GFP_KERNEL);
|
||||
if (!rm_field)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
regmap_field_init(rm_field, regmap, reg_field);
|
||||
|
||||
return rm_field;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
|
||||
|
||||
/**
|
||||
* devm_regmap_field_free(): Free register field allocated using
|
||||
* devm_regmap_field_alloc. Usally drivers need not call this function,
|
||||
* as the memory allocated via devm will be freed as per device-driver
|
||||
* life-cyle.
|
||||
*
|
||||
* @dev: Device that will be interacted with
|
||||
* @field: regmap field which should be freed.
|
||||
*/
|
||||
void devm_regmap_field_free(struct device *dev,
|
||||
struct regmap_field *field)
|
||||
{
|
||||
devm_kfree(dev, field);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_regmap_field_free);
|
||||
|
||||
/**
|
||||
* regmap_field_alloc(): Allocate and initialise a register field
|
||||
* in a register map.
|
||||
*
|
||||
* @regmap: regmap bank in which this register field is located.
|
||||
* @reg_field: Register field with in the bank.
|
||||
*
|
||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||
* to a struct regmap_field. The regmap_field should be freed by the
|
||||
* user once its finished working with it using regmap_field_free().
|
||||
*/
|
||||
struct regmap_field *regmap_field_alloc(struct regmap *regmap,
|
||||
struct reg_field reg_field)
|
||||
{
|
||||
struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
|
||||
|
||||
if (!rm_field)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
regmap_field_init(rm_field, regmap, reg_field);
|
||||
|
||||
return rm_field;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_alloc);
|
||||
|
||||
/**
|
||||
* regmap_field_free(): Free register field allocated using regmap_field_alloc
|
||||
*
|
||||
* @field: regmap field which should be freed.
|
||||
*/
|
||||
void regmap_field_free(struct regmap_field *field)
|
||||
{
|
||||
kfree(field);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_free);
|
||||
|
||||
/**
|
||||
* regmap_reinit_cache(): Reinitialise the current register cache
|
||||
*
|
||||
|
@ -1249,6 +1344,22 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_raw_write);
|
||||
|
||||
/**
|
||||
* regmap_field_write(): Write a value to a single register field
|
||||
*
|
||||
* @field: Register field to write to
|
||||
* @val: Value to be written
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_field_write(struct regmap_field *field, unsigned int val)
|
||||
{
|
||||
return regmap_update_bits(field->regmap, field->reg,
|
||||
field->mask, val << field->shift);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_write);
|
||||
|
||||
/*
|
||||
* regmap_bulk_write(): Write multiple registers to the device
|
||||
*
|
||||
|
@ -1531,6 +1642,31 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_raw_read);
|
||||
|
||||
/**
|
||||
* regmap_field_read(): Read a value to a single register field
|
||||
*
|
||||
* @field: Register field to read from
|
||||
* @val: Pointer to store read value
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_field_read(struct regmap_field *field, unsigned int *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned int reg_val;
|
||||
ret = regmap_read(field->regmap, field->reg, ®_val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
reg_val &= field->mask;
|
||||
reg_val >>= field->shift;
|
||||
*val = reg_val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_read);
|
||||
|
||||
/**
|
||||
* regmap_bulk_read(): Read multiple registers from the device
|
||||
*
|
||||
|
|
|
@ -169,6 +169,12 @@ config PINCTRL_SUNXI
|
|||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
|
||||
config PINCTRL_ST
|
||||
bool
|
||||
depends on OF
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
|
||||
config PINCTRL_TEGRA
|
||||
bool
|
||||
select PINMUX
|
||||
|
|
|
@ -46,6 +46,7 @@ obj-$(CONFIG_PINCTRL_S3C24XX) += pinctrl-s3c24xx.o
|
|||
obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
|
||||
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
|
||||
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
|
||||
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
|
||||
|
||||
obj-$(CONFIG_PLAT_ORION) += mvebu/
|
||||
obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,6 +23,7 @@ struct irq_domain;
|
|||
struct spi_device;
|
||||
struct regmap;
|
||||
struct regmap_range_cfg;
|
||||
struct regmap_field;
|
||||
|
||||
/* An enum of all the supported cache types */
|
||||
enum regcache_type {
|
||||
|
@ -394,10 +395,15 @@ bool regmap_can_raw_write(struct regmap *map);
|
|||
int regcache_sync(struct regmap *map);
|
||||
int regcache_sync_region(struct regmap *map, unsigned int min,
|
||||
unsigned int max);
|
||||
int regcache_drop_region(struct regmap *map, unsigned int min,
|
||||
unsigned int max);
|
||||
void regcache_cache_only(struct regmap *map, bool enable);
|
||||
void regcache_cache_bypass(struct regmap *map, bool enable);
|
||||
void regcache_mark_dirty(struct regmap *map);
|
||||
|
||||
bool regmap_check_range_table(struct regmap *map, unsigned int reg,
|
||||
const struct regmap_access_table *table);
|
||||
|
||||
int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
||||
int num_regs);
|
||||
|
||||
|
@ -411,6 +417,36 @@ bool regmap_reg_in_ranges(unsigned int reg,
|
|||
const struct regmap_range *ranges,
|
||||
unsigned int nranges);
|
||||
|
||||
/**
|
||||
* Description of an register field
|
||||
*
|
||||
* @reg: Offset of the register within the regmap bank
|
||||
* @lsb: lsb of the register field.
|
||||
* @reg: msb of the register field.
|
||||
*/
|
||||
struct reg_field {
|
||||
unsigned int reg;
|
||||
unsigned int lsb;
|
||||
unsigned int msb;
|
||||
};
|
||||
|
||||
#define REG_FIELD(_reg, _lsb, _msb) { \
|
||||
.reg = _reg, \
|
||||
.lsb = _lsb, \
|
||||
.msb = _msb, \
|
||||
}
|
||||
|
||||
struct regmap_field *regmap_field_alloc(struct regmap *regmap,
|
||||
struct reg_field reg_field);
|
||||
void regmap_field_free(struct regmap_field *field);
|
||||
|
||||
struct regmap_field *devm_regmap_field_alloc(struct device *dev,
|
||||
struct regmap *regmap, struct reg_field reg_field);
|
||||
void devm_regmap_field_free(struct device *dev, struct regmap_field *field);
|
||||
|
||||
int regmap_field_read(struct regmap_field *field, unsigned int *val);
|
||||
int regmap_field_write(struct regmap_field *field, unsigned int val);
|
||||
|
||||
/**
|
||||
* Description of an IRQ for the generic regmap irq_chip.
|
||||
*
|
||||
|
@ -562,6 +598,13 @@ static inline int regcache_sync_region(struct regmap *map, unsigned int min,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int regcache_drop_region(struct regmap *map, unsigned int min,
|
||||
unsigned int max)
|
||||
{
|
||||
WARN_ONCE(1, "regmap API is disabled");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline void regcache_cache_only(struct regmap *map, bool enable)
|
||||
{
|
||||
WARN_ONCE(1, "regmap API is disabled");
|
||||
|
|
|
@ -223,6 +223,29 @@ DEFINE_EVENT(regmap_async, regmap_async_complete_done,
|
|||
|
||||
);
|
||||
|
||||
TRACE_EVENT(regcache_drop_region,
|
||||
|
||||
TP_PROTO(struct device *dev, unsigned int from,
|
||||
unsigned int to),
|
||||
|
||||
TP_ARGS(dev, from, to),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string( name, dev_name(dev) )
|
||||
__field( unsigned int, from )
|
||||
__field( unsigned int, to )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, dev_name(dev));
|
||||
__entry->from = from;
|
||||
__entry->to = to;
|
||||
),
|
||||
|
||||
TP_printk("%s %u-%u", __get_str(name), (unsigned int)__entry->from,
|
||||
(unsigned int)__entry->to)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_REGMAP_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
|
Loading…
Reference in New Issue