Merge remote-tracking branches 'regmap/topic/defaults', 'regmap/topic/irq' and 'regmap/topic/reg-params' into regmap-next
This commit is contained in:
@@ -131,7 +131,10 @@ struct regmap {
|
|||||||
struct reg_default *reg_defaults;
|
struct reg_default *reg_defaults;
|
||||||
const void *reg_defaults_raw;
|
const void *reg_defaults_raw;
|
||||||
void *cache;
|
void *cache;
|
||||||
|
/* if set, the cache contains newer data than the HW */
|
||||||
u32 cache_dirty;
|
u32 cache_dirty;
|
||||||
|
/* if set, the HW registers are known to match map->reg_defaults */
|
||||||
|
bool no_sync_defaults;
|
||||||
|
|
||||||
struct reg_default *patch;
|
struct reg_default *patch;
|
||||||
int patch_regs;
|
int patch_regs;
|
||||||
|
|||||||
@@ -249,6 +249,22 @@ int regcache_write(struct regmap *map,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
|
||||||
|
unsigned int val)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* If we don't know the chip just got reset, then sync everything. */
|
||||||
|
if (!map->no_sync_defaults)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Is this the hardware default? If so skip. */
|
||||||
|
ret = regcache_lookup_reg(map, reg);
|
||||||
|
if (ret >= 0 && val == map->reg_defaults[ret].def)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int regcache_default_sync(struct regmap *map, unsigned int min,
|
static int regcache_default_sync(struct regmap *map, unsigned int min,
|
||||||
unsigned int max)
|
unsigned int max)
|
||||||
{
|
{
|
||||||
@@ -266,9 +282,7 @@ static int regcache_default_sync(struct regmap *map, unsigned int min,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Is this the hardware default? If so skip. */
|
if (!regcache_reg_needs_sync(map, reg, val))
|
||||||
ret = regcache_lookup_reg(map, reg);
|
|
||||||
if (ret >= 0 && val == map->reg_defaults[ret].def)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
map->cache_bypass = 1;
|
map->cache_bypass = 1;
|
||||||
@@ -342,6 +356,7 @@ out:
|
|||||||
/* Restore the bypass state */
|
/* Restore the bypass state */
|
||||||
map->async = false;
|
map->async = false;
|
||||||
map->cache_bypass = bypass;
|
map->cache_bypass = bypass;
|
||||||
|
map->no_sync_defaults = false;
|
||||||
map->unlock(map->lock_arg);
|
map->unlock(map->lock_arg);
|
||||||
|
|
||||||
regmap_async_complete(map);
|
regmap_async_complete(map);
|
||||||
@@ -397,6 +412,7 @@ out:
|
|||||||
/* Restore the bypass state */
|
/* Restore the bypass state */
|
||||||
map->cache_bypass = bypass;
|
map->cache_bypass = bypass;
|
||||||
map->async = false;
|
map->async = false;
|
||||||
|
map->no_sync_defaults = false;
|
||||||
map->unlock(map->lock_arg);
|
map->unlock(map->lock_arg);
|
||||||
|
|
||||||
regmap_async_complete(map);
|
regmap_async_complete(map);
|
||||||
@@ -461,18 +477,23 @@ void regcache_cache_only(struct regmap *map, bool enable)
|
|||||||
EXPORT_SYMBOL_GPL(regcache_cache_only);
|
EXPORT_SYMBOL_GPL(regcache_cache_only);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* regcache_mark_dirty: Mark the register cache as dirty
|
* regcache_mark_dirty: Indicate that HW registers were reset to default values
|
||||||
*
|
*
|
||||||
* @map: map to mark
|
* @map: map to mark
|
||||||
*
|
*
|
||||||
* Mark the register cache as dirty, for example due to the device
|
* Inform regcache that the device has been powered down or reset, so that
|
||||||
* having been powered down for suspend. If the cache is not marked
|
* on resume, regcache_sync() knows to write out all non-default values
|
||||||
* as dirty then the cache sync will be suppressed.
|
* stored in the cache.
|
||||||
|
*
|
||||||
|
* If this function is not called, regcache_sync() will assume that
|
||||||
|
* the hardware state still matches the cache state, modulo any writes that
|
||||||
|
* happened when cache_only was true.
|
||||||
*/
|
*/
|
||||||
void regcache_mark_dirty(struct regmap *map)
|
void regcache_mark_dirty(struct regmap *map)
|
||||||
{
|
{
|
||||||
map->lock(map->lock_arg);
|
map->lock(map->lock_arg);
|
||||||
map->cache_dirty = true;
|
map->cache_dirty = true;
|
||||||
|
map->no_sync_defaults = true;
|
||||||
map->unlock(map->lock_arg);
|
map->unlock(map->lock_arg);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regcache_mark_dirty);
|
EXPORT_SYMBOL_GPL(regcache_mark_dirty);
|
||||||
@@ -613,10 +634,7 @@ static int regcache_sync_block_single(struct regmap *map, void *block,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
val = regcache_get_val(map, block, i);
|
val = regcache_get_val(map, block, i);
|
||||||
|
if (!regcache_reg_needs_sync(map, regtmp, val))
|
||||||
/* Is this the hardware default? If so skip. */
|
|
||||||
ret = regcache_lookup_reg(map, regtmp);
|
|
||||||
if (ret >= 0 && val == map->reg_defaults[ret].def)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
map->cache_bypass = 1;
|
map->cache_bypass = 1;
|
||||||
@@ -688,10 +706,7 @@ static int regcache_sync_block_raw(struct regmap *map, void *block,
|
|||||||
}
|
}
|
||||||
|
|
||||||
val = regcache_get_val(map, block, i);
|
val = regcache_get_val(map, block, i);
|
||||||
|
if (!regcache_reg_needs_sync(map, regtmp, val)) {
|
||||||
/* Is this the hardware default? If so skip. */
|
|
||||||
ret = regcache_lookup_reg(map, regtmp);
|
|
||||||
if (ret >= 0 && val == map->reg_defaults[ret].def) {
|
|
||||||
ret = regcache_sync_block_raw_flush(map, &data,
|
ret = regcache_sync_block_raw_flush(map, &data,
|
||||||
base, regtmp);
|
base, regtmp);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
|
|||||||
if (!d->chip->init_ack_masked)
|
if (!d->chip->init_ack_masked)
|
||||||
continue;
|
continue;
|
||||||
/*
|
/*
|
||||||
* Ack all the masked interrupts uncondictionly,
|
* Ack all the masked interrupts unconditionally,
|
||||||
* OR if there is masked interrupt which hasn't been Acked,
|
* OR if there is masked interrupt which hasn't been Acked,
|
||||||
* it'll be ignored in irq handler, then may introduce irq storm
|
* it'll be ignored in irq handler, then may introduce irq storm
|
||||||
*/
|
*/
|
||||||
@@ -306,19 +306,12 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
|
|||||||
irq_set_chip_data(virq, data);
|
irq_set_chip_data(virq, data);
|
||||||
irq_set_chip(virq, &data->irq_chip);
|
irq_set_chip(virq, &data->irq_chip);
|
||||||
irq_set_nested_thread(virq, 1);
|
irq_set_nested_thread(virq, 1);
|
||||||
|
|
||||||
/* ARM needs us to explicitly flag the IRQ as valid
|
|
||||||
* and will set them noprobe when we do so. */
|
|
||||||
#ifdef CONFIG_ARM
|
|
||||||
set_irq_flags(virq, IRQF_VALID);
|
|
||||||
#else
|
|
||||||
irq_set_noprobe(virq);
|
irq_set_noprobe(virq);
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_domain_ops regmap_domain_ops = {
|
static const struct irq_domain_ops regmap_domain_ops = {
|
||||||
.map = regmap_irq_map,
|
.map = regmap_irq_map,
|
||||||
.xlate = irq_domain_xlate_twocell,
|
.xlate = irq_domain_xlate_twocell,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2609,6 +2609,30 @@ int regmap_get_val_bytes(struct regmap *map)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
|
EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regmap_get_max_register(): Report the max register value
|
||||||
|
*
|
||||||
|
* Report the max register value, mainly intended to for use by
|
||||||
|
* generic infrastructure built on top of regmap.
|
||||||
|
*/
|
||||||
|
int regmap_get_max_register(struct regmap *map)
|
||||||
|
{
|
||||||
|
return map->max_register ? map->max_register : -EINVAL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(regmap_get_max_register);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regmap_get_reg_stride(): Report the register address stride
|
||||||
|
*
|
||||||
|
* Report the register address stride, mainly intended to for use by
|
||||||
|
* generic infrastructure built on top of regmap.
|
||||||
|
*/
|
||||||
|
int regmap_get_reg_stride(struct regmap *map)
|
||||||
|
{
|
||||||
|
return map->reg_stride;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(regmap_get_reg_stride);
|
||||||
|
|
||||||
int regmap_parse_val(struct regmap *map, const void *buf,
|
int regmap_parse_val(struct regmap *map, const void *buf,
|
||||||
unsigned int *val)
|
unsigned int *val)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -433,6 +433,8 @@ int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
|
|||||||
unsigned int mask, unsigned int val,
|
unsigned int mask, unsigned int val,
|
||||||
bool *change);
|
bool *change);
|
||||||
int regmap_get_val_bytes(struct regmap *map);
|
int regmap_get_val_bytes(struct regmap *map);
|
||||||
|
int regmap_get_max_register(struct regmap *map);
|
||||||
|
int regmap_get_reg_stride(struct regmap *map);
|
||||||
int regmap_async_complete(struct regmap *map);
|
int regmap_async_complete(struct regmap *map);
|
||||||
bool regmap_can_raw_write(struct regmap *map);
|
bool regmap_can_raw_write(struct regmap *map);
|
||||||
|
|
||||||
@@ -676,6 +678,18 @@ static inline int regmap_get_val_bytes(struct regmap *map)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int regmap_get_max_register(struct regmap *map)
|
||||||
|
{
|
||||||
|
WARN_ONCE(1, "regmap API is disabled");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int regmap_get_reg_stride(struct regmap *map)
|
||||||
|
{
|
||||||
|
WARN_ONCE(1, "regmap API is disabled");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int regcache_sync(struct regmap *map)
|
static inline int regcache_sync(struct regmap *map)
|
||||||
{
|
{
|
||||||
WARN_ONCE(1, "regmap API is disabled");
|
WARN_ONCE(1, "regmap API is disabled");
|
||||||
|
|||||||
Reference in New Issue
Block a user