Skip to content

Commit cdf6b11

Browse files
BWhittenbroonie
authored andcommitted
regmap: Add regmap_noinc_write API
The regmap API had a noinc_read function added for instances where devices supported returning data from an internal FIFO in a single read. This commit adds the noinc_write variant to allow writing to a non incrementing register, this is used in devices such as the sx1301 for loading firmware. Signed-off-by: Ben Whitten <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 5b394b2 commit cdf6b11

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

drivers/base/regmap/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,13 @@ struct regmap {
9494
bool (*readable_reg)(struct device *dev, unsigned int reg);
9595
bool (*volatile_reg)(struct device *dev, unsigned int reg);
9696
bool (*precious_reg)(struct device *dev, unsigned int reg);
97+
bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg);
9798
bool (*readable_noinc_reg)(struct device *dev, unsigned int reg);
9899
const struct regmap_access_table *wr_table;
99100
const struct regmap_access_table *rd_table;
100101
const struct regmap_access_table *volatile_table;
101102
const struct regmap_access_table *precious_table;
103+
const struct regmap_access_table *wr_noinc_table;
102104
const struct regmap_access_table *rd_noinc_table;
103105

104106
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
@@ -183,6 +185,7 @@ bool regmap_writeable(struct regmap *map, unsigned int reg);
183185
bool regmap_readable(struct regmap *map, unsigned int reg);
184186
bool regmap_volatile(struct regmap *map, unsigned int reg);
185187
bool regmap_precious(struct regmap *map, unsigned int reg);
188+
bool regmap_writeable_noinc(struct regmap *map, unsigned int reg);
186189
bool regmap_readable_noinc(struct regmap *map, unsigned int reg);
187190

188191
int _regmap_write(struct regmap *map, unsigned int reg,

drivers/base/regmap/regmap.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,17 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
168168
return false;
169169
}
170170

171+
bool regmap_writeable_noinc(struct regmap *map, unsigned int reg)
172+
{
173+
if (map->writeable_noinc_reg)
174+
return map->writeable_noinc_reg(map->dev, reg);
175+
176+
if (map->wr_noinc_table)
177+
return regmap_check_range_table(map, reg, map->wr_noinc_table);
178+
179+
return true;
180+
}
181+
171182
bool regmap_readable_noinc(struct regmap *map, unsigned int reg)
172183
{
173184
if (map->readable_noinc_reg)
@@ -777,11 +788,13 @@ struct regmap *__regmap_init(struct device *dev,
777788
map->rd_table = config->rd_table;
778789
map->volatile_table = config->volatile_table;
779790
map->precious_table = config->precious_table;
791+
map->wr_noinc_table = config->wr_noinc_table;
780792
map->rd_noinc_table = config->rd_noinc_table;
781793
map->writeable_reg = config->writeable_reg;
782794
map->readable_reg = config->readable_reg;
783795
map->volatile_reg = config->volatile_reg;
784796
map->precious_reg = config->precious_reg;
797+
map->writeable_noinc_reg = config->writeable_noinc_reg;
785798
map->readable_noinc_reg = config->readable_noinc_reg;
786799
map->cache_type = config->cache_type;
787800

@@ -1298,6 +1311,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
12981311
map->readable_reg = config->readable_reg;
12991312
map->volatile_reg = config->volatile_reg;
13001313
map->precious_reg = config->precious_reg;
1314+
map->writeable_noinc_reg = config->writeable_noinc_reg;
13011315
map->readable_noinc_reg = config->readable_noinc_reg;
13021316
map->cache_type = config->cache_type;
13031317

@@ -1897,6 +1911,69 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
18971911
}
18981912
EXPORT_SYMBOL_GPL(regmap_raw_write);
18991913

1914+
/**
1915+
* regmap_noinc_write(): Write data from a register without incrementing the
1916+
* register number
1917+
*
1918+
* @map: Register map to write to
1919+
* @reg: Register to write to
1920+
* @val: Pointer to data buffer
1921+
* @val_len: Length of output buffer in bytes.
1922+
*
1923+
* The regmap API usually assumes that bulk bus write operations will write a
1924+
* range of registers. Some devices have certain registers for which a write
1925+
* operation can write to an internal FIFO.
1926+
*
1927+
* The target register must be volatile but registers after it can be
1928+
* completely unrelated cacheable registers.
1929+
*
1930+
* This will attempt multiple writes as required to write val_len bytes.
1931+
*
1932+
* A value of zero will be returned on success, a negative errno will be
1933+
* returned in error cases.
1934+
*/
1935+
int regmap_noinc_write(struct regmap *map, unsigned int reg,
1936+
const void *val, size_t val_len)
1937+
{
1938+
size_t write_len;
1939+
int ret;
1940+
1941+
if (!map->bus)
1942+
return -EINVAL;
1943+
if (!map->bus->write)
1944+
return -ENOTSUPP;
1945+
if (val_len % map->format.val_bytes)
1946+
return -EINVAL;
1947+
if (!IS_ALIGNED(reg, map->reg_stride))
1948+
return -EINVAL;
1949+
if (val_len == 0)
1950+
return -EINVAL;
1951+
1952+
map->lock(map->lock_arg);
1953+
1954+
if (!regmap_volatile(map, reg) || !regmap_writeable_noinc(map, reg)) {
1955+
ret = -EINVAL;
1956+
goto out_unlock;
1957+
}
1958+
1959+
while (val_len) {
1960+
if (map->max_raw_write && map->max_raw_write < val_len)
1961+
write_len = map->max_raw_write;
1962+
else
1963+
write_len = val_len;
1964+
ret = _regmap_raw_write(map, reg, val, write_len);
1965+
if (ret)
1966+
goto out_unlock;
1967+
val = ((u8 *)val) + write_len;
1968+
val_len -= write_len;
1969+
}
1970+
1971+
out_unlock:
1972+
map->unlock(map->lock_arg);
1973+
return ret;
1974+
}
1975+
EXPORT_SYMBOL_GPL(regmap_noinc_write);
1976+
19001977
/**
19011978
* regmap_field_update_bits_base() - Perform a read/modify/write cycle a
19021979
* register field.

include/linux/regmap.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,13 @@ typedef void (*regmap_unlock)(void *);
268268
* field is NULL but precious_table (see below) is not, the
269269
* check is performed on such table (a register is precious if
270270
* it belongs to one of the ranges specified by precious_table).
271+
* @writeable_noinc_reg: Optional callback returning true if the register
272+
* supports multiple write operations without incrementing
273+
* the register number. If this field is NULL but
274+
* wr_noinc_table (see below) is not, the check is
275+
* performed on such table (a register is no increment
276+
* writeable if it belongs to one of the ranges specified
277+
* by wr_noinc_table).
271278
* @readable_noinc_reg: Optional callback returning true if the register
272279
* supports multiple read operations without incrementing
273280
* the register number. If this field is NULL but
@@ -302,6 +309,7 @@ typedef void (*regmap_unlock)(void *);
302309
* @rd_table: As above, for read access.
303310
* @volatile_table: As above, for volatile registers.
304311
* @precious_table: As above, for precious registers.
312+
* @wr_noinc_table: As above, for no increment writeable registers.
305313
* @rd_noinc_table: As above, for no increment readable registers.
306314
* @reg_defaults: Power on reset values for registers (for use with
307315
* register cache support).
@@ -352,6 +360,7 @@ struct regmap_config {
352360
bool (*readable_reg)(struct device *dev, unsigned int reg);
353361
bool (*volatile_reg)(struct device *dev, unsigned int reg);
354362
bool (*precious_reg)(struct device *dev, unsigned int reg);
363+
bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg);
355364
bool (*readable_noinc_reg)(struct device *dev, unsigned int reg);
356365

357366
bool disable_locking;
@@ -369,6 +378,7 @@ struct regmap_config {
369378
const struct regmap_access_table *rd_table;
370379
const struct regmap_access_table *volatile_table;
371380
const struct regmap_access_table *precious_table;
381+
const struct regmap_access_table *wr_noinc_table;
372382
const struct regmap_access_table *rd_noinc_table;
373383
const struct reg_default *reg_defaults;
374384
unsigned int num_reg_defaults;
@@ -979,6 +989,8 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
979989
int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val);
980990
int regmap_raw_write(struct regmap *map, unsigned int reg,
981991
const void *val, size_t val_len);
992+
int regmap_noinc_write(struct regmap *map, unsigned int reg,
993+
const void *val, size_t val_len);
982994
int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
983995
size_t val_count);
984996
int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs,
@@ -1222,6 +1234,13 @@ static inline int regmap_raw_write_async(struct regmap *map, unsigned int reg,
12221234
return -EINVAL;
12231235
}
12241236

1237+
static inline int regmap_noinc_write(struct regmap *map, unsigned int reg,
1238+
const void *val, size_t val_len)
1239+
{
1240+
WARN_ONCE(1, "regmap API is disabled");
1241+
return -EINVAL;
1242+
}
1243+
12251244
static inline int regmap_bulk_write(struct regmap *map, unsigned int reg,
12261245
const void *val, size_t val_count)
12271246
{

0 commit comments

Comments
 (0)