Skip to content

Commit 6f10810

Browse files
committed
Merge tag 'regmap-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap updates from Mark Brown: "There's one big bit of work this time around, the addition of support for a greater range of MBQ access sizes to SoundWire devices together with support for deferred read/write. The MBQ register maps generally have variable register sizes, the variable regiseter size support allows them to be handled much more naturally within regmap with less open coding in drivers. The deferred read/write support avoids spurious errors when devices make use of a bus feature allowing them to indicate they're busy. These changes pull in a supporting SoundWire change, and there's an ASoC change building off the new code. The remainder of the changes are code cleanups" * tag 'regmap-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: sdw-mbq: Add support for SDCA deferred controls regmap: sdw-mbq: Add support for further MBQ register sizes ASoC: SDCA: Update list of entity_0 controls soundwire: SDCA: Add additional SDCA address macros regmap: regmap_multi_reg_read(): make register list const regmap: cache: rbtree: use krealloc_array() to replace krealloc() regmap: cache: mapple: use kmalloc_array() to replace kmalloc() regmap: place foo / 8 and foo % 8 closer to each other regmap: Use BITS_TO_BYTES() regmap: cache: Use BITS_TO_BYTES()
2 parents 0c93431 + d406b35 commit 6f10810

File tree

8 files changed

+319
-59
lines changed

8 files changed

+319
-59
lines changed

drivers/base/regmap/regcache-maple.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ static int regcache_maple_write(struct regmap *map, unsigned int reg,
7373

7474
rcu_read_unlock();
7575

76-
entry = kmalloc((last - index + 1) * sizeof(unsigned long),
77-
map->alloc_flags);
76+
entry = kmalloc_array(last - index + 1, sizeof(*entry), map->alloc_flags);
7877
if (!entry)
7978
return -ENOMEM;
8079

@@ -204,7 +203,7 @@ static int regcache_maple_sync_block(struct regmap *map, unsigned long *entry,
204203
* overheads.
205204
*/
206205
if (max - min > 1 && regmap_can_raw_write(map)) {
207-
buf = kmalloc(val_bytes * (max - min), map->alloc_flags);
206+
buf = kmalloc_array(max - min, val_bytes, map->alloc_flags);
208207
if (!buf) {
209208
ret = -ENOMEM;
210209
goto out;
@@ -320,7 +319,7 @@ static int regcache_maple_insert_block(struct regmap *map, int first,
320319
unsigned long *entry;
321320
int i, ret;
322321

323-
entry = kcalloc(last - first + 1, sizeof(unsigned long), map->alloc_flags);
322+
entry = kmalloc_array(last - first + 1, sizeof(*entry), map->alloc_flags);
324323
if (!entry)
325324
return -ENOMEM;
326325

drivers/base/regmap/regcache-rbtree.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,18 +275,16 @@ static int regcache_rbtree_insert_to_block(struct regmap *map,
275275
pos = (reg - base_reg) / map->reg_stride;
276276
offset = (rbnode->base_reg - base_reg) / map->reg_stride;
277277

278-
blk = krealloc(rbnode->block,
279-
blklen * map->cache_word_size,
280-
map->alloc_flags);
278+
blk = krealloc_array(rbnode->block, blklen, map->cache_word_size, map->alloc_flags);
281279
if (!blk)
282280
return -ENOMEM;
283281

284282
rbnode->block = blk;
285283

286284
if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) {
287-
present = krealloc(rbnode->cache_present,
288-
BITS_TO_LONGS(blklen) * sizeof(*present),
289-
map->alloc_flags);
285+
present = krealloc_array(rbnode->cache_present,
286+
BITS_TO_LONGS(blklen), sizeof(*present),
287+
map->alloc_flags);
290288
if (!present)
291289
return -ENOMEM;
292290

drivers/base/regmap/regcache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
154154
map->num_reg_defaults = config->num_reg_defaults;
155155
map->num_reg_defaults_raw = config->num_reg_defaults_raw;
156156
map->reg_defaults_raw = config->reg_defaults_raw;
157-
map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8);
157+
map->cache_word_size = BITS_TO_BYTES(config->val_bits);
158158
map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw;
159159

160160
map->cache = NULL;

drivers/base/regmap/regmap-sdw-mbq.c

Lines changed: 197 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,187 @@
11
// SPDX-License-Identifier: GPL-2.0
22
// Copyright(c) 2020 Intel Corporation.
33

4+
#include <linux/bits.h>
5+
#include <linux/delay.h>
46
#include <linux/device.h>
57
#include <linux/errno.h>
8+
#include <linux/iopoll.h>
69
#include <linux/module.h>
710
#include <linux/regmap.h>
811
#include <linux/soundwire/sdw.h>
912
#include <linux/soundwire/sdw_registers.h>
13+
#include <sound/sdca_function.h>
1014
#include "internal.h"
1115

16+
struct regmap_mbq_context {
17+
struct device *dev;
18+
19+
struct regmap_sdw_mbq_cfg cfg;
20+
21+
int val_size;
22+
bool (*readable_reg)(struct device *dev, unsigned int reg);
23+
};
24+
25+
static int regmap_sdw_mbq_size(struct regmap_mbq_context *ctx, unsigned int reg)
26+
{
27+
int size = ctx->val_size;
28+
29+
if (ctx->cfg.mbq_size) {
30+
size = ctx->cfg.mbq_size(ctx->dev, reg);
31+
if (!size || size > ctx->val_size)
32+
return -EINVAL;
33+
}
34+
35+
return size;
36+
}
37+
38+
static bool regmap_sdw_mbq_deferrable(struct regmap_mbq_context *ctx, unsigned int reg)
39+
{
40+
if (ctx->cfg.deferrable)
41+
return ctx->cfg.deferrable(ctx->dev, reg);
42+
43+
return false;
44+
}
45+
46+
static int regmap_sdw_mbq_poll_busy(struct sdw_slave *slave, unsigned int reg,
47+
struct regmap_mbq_context *ctx)
48+
{
49+
struct device *dev = &slave->dev;
50+
int val, ret = 0;
51+
52+
dev_dbg(dev, "Deferring transaction for 0x%x\n", reg);
53+
54+
reg = SDW_SDCA_CTL(SDW_SDCA_CTL_FUNC(reg), 0,
55+
SDCA_CTL_ENTITY_0_FUNCTION_STATUS, 0);
56+
57+
if (ctx->readable_reg(dev, reg)) {
58+
ret = read_poll_timeout(sdw_read_no_pm, val,
59+
val < 0 || !(val & SDCA_CTL_ENTITY_0_FUNCTION_BUSY),
60+
ctx->cfg.timeout_us, ctx->cfg.retry_us,
61+
false, slave, reg);
62+
if (val < 0)
63+
return val;
64+
if (ret)
65+
dev_err(dev, "Function busy timed out 0x%x: %d\n", reg, val);
66+
} else {
67+
fsleep(ctx->cfg.timeout_us);
68+
}
69+
70+
return ret;
71+
}
72+
73+
static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave,
74+
unsigned int reg, unsigned int val,
75+
int mbq_size, bool deferrable)
76+
{
77+
int shift = mbq_size * BITS_PER_BYTE;
78+
int ret;
79+
80+
while (--mbq_size > 0) {
81+
shift -= BITS_PER_BYTE;
82+
83+
ret = sdw_write_no_pm(slave, SDW_SDCA_MBQ_CTL(reg),
84+
(val >> shift) & 0xff);
85+
if (ret < 0)
86+
return ret;
87+
}
88+
89+
ret = sdw_write_no_pm(slave, reg, val & 0xff);
90+
if (deferrable && ret == -ENODATA)
91+
return -EAGAIN;
92+
93+
return ret;
94+
}
95+
1296
static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val)
1397
{
14-
struct device *dev = context;
98+
struct regmap_mbq_context *ctx = context;
99+
struct device *dev = ctx->dev;
15100
struct sdw_slave *slave = dev_to_sdw_dev(dev);
101+
bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg);
102+
int mbq_size = regmap_sdw_mbq_size(ctx, reg);
16103
int ret;
17104

18-
ret = sdw_write_no_pm(slave, SDW_SDCA_MBQ_CTL(reg), (val >> 8) & 0xff);
19-
if (ret < 0)
20-
return ret;
105+
if (mbq_size < 0)
106+
return mbq_size;
107+
108+
/*
109+
* Technically the spec does allow a device to set itself to busy for
110+
* internal reasons, but since it doesn't provide any information on
111+
* how to handle timeouts in that case, for now the code will only
112+
* process a single wait/timeout on function busy and a single retry
113+
* of the transaction.
114+
*/
115+
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, deferrable);
116+
if (ret == -EAGAIN) {
117+
ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx);
118+
if (ret)
119+
return ret;
120+
121+
ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, false);
122+
}
123+
124+
return ret;
125+
}
126+
127+
static int regmap_sdw_mbq_read_impl(struct sdw_slave *slave,
128+
unsigned int reg, unsigned int *val,
129+
int mbq_size, bool deferrable)
130+
{
131+
int shift = BITS_PER_BYTE;
132+
int read;
133+
134+
read = sdw_read_no_pm(slave, reg);
135+
if (read < 0) {
136+
if (deferrable && read == -ENODATA)
137+
return -EAGAIN;
138+
139+
return read;
140+
}
141+
142+
*val = read;
143+
144+
while (--mbq_size > 0) {
145+
read = sdw_read_no_pm(slave, SDW_SDCA_MBQ_CTL(reg));
146+
if (read < 0)
147+
return read;
148+
149+
*val |= read << shift;
150+
shift += BITS_PER_BYTE;
151+
}
21152

22-
return sdw_write_no_pm(slave, reg, val & 0xff);
153+
return 0;
23154
}
24155

25156
static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *val)
26157
{
27-
struct device *dev = context;
158+
struct regmap_mbq_context *ctx = context;
159+
struct device *dev = ctx->dev;
28160
struct sdw_slave *slave = dev_to_sdw_dev(dev);
29-
int read0;
30-
int read1;
161+
bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg);
162+
int mbq_size = regmap_sdw_mbq_size(ctx, reg);
163+
int ret;
31164

32-
read0 = sdw_read_no_pm(slave, reg);
33-
if (read0 < 0)
34-
return read0;
165+
if (mbq_size < 0)
166+
return mbq_size;
35167

36-
read1 = sdw_read_no_pm(slave, SDW_SDCA_MBQ_CTL(reg));
37-
if (read1 < 0)
38-
return read1;
168+
/*
169+
* Technically the spec does allow a device to set itself to busy for
170+
* internal reasons, but since it doesn't provide any information on
171+
* how to handle timeouts in that case, for now the code will only
172+
* process a single wait/timeout on function busy and a single retry
173+
* of the transaction.
174+
*/
175+
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, deferrable);
176+
if (ret == -EAGAIN) {
177+
ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx);
178+
if (ret)
179+
return ret;
39180

40-
*val = (read1 << 8) | read0;
181+
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, false);
182+
}
41183

42-
return 0;
184+
return ret;
43185
}
44186

45187
static const struct regmap_bus regmap_sdw_mbq = {
@@ -51,8 +193,7 @@ static const struct regmap_bus regmap_sdw_mbq = {
51193

52194
static int regmap_sdw_mbq_config_check(const struct regmap_config *config)
53195
{
54-
/* MBQ-based controls are only 16-bits for now */
55-
if (config->val_bits != 16)
196+
if (config->val_bits > (sizeof(unsigned int) * BITS_PER_BYTE))
56197
return -ENOTSUPP;
57198

58199
/* Registers are 32 bits wide */
@@ -65,35 +206,69 @@ static int regmap_sdw_mbq_config_check(const struct regmap_config *config)
65206
return 0;
66207
}
67208

209+
static struct regmap_mbq_context *
210+
regmap_sdw_mbq_gen_context(struct device *dev,
211+
const struct regmap_config *config,
212+
const struct regmap_sdw_mbq_cfg *mbq_config)
213+
{
214+
struct regmap_mbq_context *ctx;
215+
216+
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
217+
if (!ctx)
218+
return ERR_PTR(-ENOMEM);
219+
220+
ctx->dev = dev;
221+
222+
if (mbq_config)
223+
ctx->cfg = *mbq_config;
224+
225+
ctx->val_size = config->val_bits / BITS_PER_BYTE;
226+
ctx->readable_reg = config->readable_reg;
227+
228+
return ctx;
229+
}
230+
68231
struct regmap *__regmap_init_sdw_mbq(struct sdw_slave *sdw,
69232
const struct regmap_config *config,
233+
const struct regmap_sdw_mbq_cfg *mbq_config,
70234
struct lock_class_key *lock_key,
71235
const char *lock_name)
72236
{
237+
struct regmap_mbq_context *ctx;
73238
int ret;
74239

75240
ret = regmap_sdw_mbq_config_check(config);
76241
if (ret)
77242
return ERR_PTR(ret);
78243

79-
return __regmap_init(&sdw->dev, &regmap_sdw_mbq,
80-
&sdw->dev, config, lock_key, lock_name);
244+
ctx = regmap_sdw_mbq_gen_context(&sdw->dev, config, mbq_config);
245+
if (IS_ERR(ctx))
246+
return ERR_CAST(ctx);
247+
248+
return __regmap_init(&sdw->dev, &regmap_sdw_mbq, ctx,
249+
config, lock_key, lock_name);
81250
}
82251
EXPORT_SYMBOL_GPL(__regmap_init_sdw_mbq);
83252

84253
struct regmap *__devm_regmap_init_sdw_mbq(struct sdw_slave *sdw,
85254
const struct regmap_config *config,
255+
const struct regmap_sdw_mbq_cfg *mbq_config,
86256
struct lock_class_key *lock_key,
87257
const char *lock_name)
88258
{
259+
struct regmap_mbq_context *ctx;
89260
int ret;
90261

91262
ret = regmap_sdw_mbq_config_check(config);
92263
if (ret)
93264
return ERR_PTR(ret);
94265

95-
return __devm_regmap_init(&sdw->dev, &regmap_sdw_mbq,
96-
&sdw->dev, config, lock_key, lock_name);
266+
ctx = regmap_sdw_mbq_gen_context(&sdw->dev, config, mbq_config);
267+
if (IS_ERR(ctx))
268+
return ERR_CAST(ctx);
269+
270+
return __devm_regmap_init(&sdw->dev, &regmap_sdw_mbq, ctx,
271+
config, lock_key, lock_name);
97272
}
98273
EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw_mbq);
99274

drivers/base/regmap/regmap.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -769,14 +769,13 @@ struct regmap *__regmap_init(struct device *dev,
769769
map->alloc_flags = GFP_KERNEL;
770770

771771
map->reg_base = config->reg_base;
772+
map->reg_shift = config->pad_bits % 8;
772773

773-
map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
774774
map->format.pad_bytes = config->pad_bits / 8;
775775
map->format.reg_shift = config->reg_shift;
776-
map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
777-
map->format.buf_size = DIV_ROUND_UP(config->reg_bits +
778-
config->val_bits + config->pad_bits, 8);
779-
map->reg_shift = config->pad_bits % 8;
776+
map->format.reg_bytes = BITS_TO_BYTES(config->reg_bits);
777+
map->format.val_bytes = BITS_TO_BYTES(config->val_bits);
778+
map->format.buf_size = BITS_TO_BYTES(config->reg_bits + config->val_bits + config->pad_bits);
780779
if (config->reg_stride)
781780
map->reg_stride = config->reg_stride;
782781
else
@@ -3116,7 +3115,7 @@ int regmap_fields_read(struct regmap_field *field, unsigned int id,
31163115
EXPORT_SYMBOL_GPL(regmap_fields_read);
31173116

31183117
static int _regmap_bulk_read(struct regmap *map, unsigned int reg,
3119-
unsigned int *regs, void *val, size_t val_count)
3118+
const unsigned int *regs, void *val, size_t val_count)
31203119
{
31213120
u32 *u32 = val;
31223121
u16 *u16 = val;
@@ -3210,7 +3209,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_read);
32103209
* A value of zero will be returned on success, a negative errno will
32113210
* be returned in error cases.
32123211
*/
3213-
int regmap_multi_reg_read(struct regmap *map, unsigned int *regs, void *val,
3212+
int regmap_multi_reg_read(struct regmap *map, const unsigned int *regs, void *val,
32143213
size_t val_count)
32153214
{
32163215
if (val_count == 0)

0 commit comments

Comments
 (0)