Skip to content

Commit 9b6c4c4

Browse files
committed
Merge remote-tracking branch 'regmap/for-next' into sound/upstream-20250114
2 parents 16766e8 + d406b35 commit 9b6c4c4

8 files changed

Lines changed: 319 additions & 59 deletions

File tree

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)