Commit 70ee853e authored by Richard Fitzgerald's avatar Richard Fitzgerald Committed by Mark Brown

regmap: Add regmap_read_bypassed()

Add a regmap_read_bypassed() to allow reads from the hardware registers
while the regmap is in cache-only mode.

A typical use for this is to keep the cache in cache-only mode until
the hardware has reached a valid state, but one or more status registers
must be polled to determine when this state is reached.

For example, firmware download on the cs35l56 can take several seconds if
there are multiple amps sharing limited bus bandwidth. This is too long
to block in probe() so it is done as a background task. The device must
be soft-reset to reboot the firmware and during this time the registers are
not accessible, so the cache should be in cache-only. But the driver must
poll a register to detect when reboot has completed.
Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
Fixes: 8a731fd3 ("ASoC: cs35l56: Move utility functions to shared file")
Link: https://msgid.link/r/20240408101803.43183-2-rf@opensource.cirrus.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent fec50db7
...@@ -2838,6 +2838,43 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) ...@@ -2838,6 +2838,43 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
} }
EXPORT_SYMBOL_GPL(regmap_read); EXPORT_SYMBOL_GPL(regmap_read);
/**
* regmap_read_bypassed() - Read a value from a single register direct
* from the device, bypassing the cache
*
* @map: Register map to read from
* @reg: Register to be 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_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val)
{
int ret;
bool bypass, cache_only;
if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
map->lock(map->lock_arg);
bypass = map->cache_bypass;
cache_only = map->cache_only;
map->cache_bypass = true;
map->cache_only = false;
ret = _regmap_read(map, reg, val);
map->cache_bypass = bypass;
map->cache_only = cache_only;
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_read_bypassed);
/** /**
* regmap_raw_read() - Read raw data from the device * regmap_raw_read() - Read raw data from the device
* *
......
...@@ -1230,6 +1230,7 @@ int regmap_multi_reg_write_bypassed(struct regmap *map, ...@@ -1230,6 +1230,7 @@ int regmap_multi_reg_write_bypassed(struct regmap *map,
int regmap_raw_write_async(struct regmap *map, unsigned int reg, int regmap_raw_write_async(struct regmap *map, unsigned int reg,
const void *val, size_t val_len); const void *val, size_t val_len);
int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val);
int regmap_raw_read(struct regmap *map, unsigned int reg, int regmap_raw_read(struct regmap *map, unsigned int reg,
void *val, size_t val_len); void *val, size_t val_len);
int regmap_noinc_read(struct regmap *map, unsigned int reg, int regmap_noinc_read(struct regmap *map, unsigned int reg,
...@@ -1739,6 +1740,13 @@ static inline int regmap_read(struct regmap *map, unsigned int reg, ...@@ -1739,6 +1740,13 @@ static inline int regmap_read(struct regmap *map, unsigned int reg,
return -EINVAL; return -EINVAL;
} }
static inline int regmap_read_bypassed(struct regmap *map, unsigned int reg,
unsigned int *val)
{
WARN_ONCE(1, "regmap API is disabled");
return -EINVAL;
}
static inline int regmap_raw_read(struct regmap *map, unsigned int reg, static inline int regmap_raw_read(struct regmap *map, unsigned int reg,
void *val, size_t val_len) void *val, size_t val_len)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment