1 // SPDX-License-Identifier: GPL-2.0
3 // Register map access API - MMIO support
5 // Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
10 #include <linux/module.h>
11 #include <linux/regmap.h>
12 #include <linux/slab.h>
13 #include <linux/swab.h>
17 struct regmap_mmio_context
{
19 unsigned int val_bytes
;
25 void (*reg_write
)(struct regmap_mmio_context
*ctx
,
26 unsigned int reg
, unsigned int val
);
27 unsigned int (*reg_read
)(struct regmap_mmio_context
*ctx
,
31 static int regmap_mmio_regbits_check(size_t reg_bits
)
43 static int regmap_mmio_get_min_stride(size_t val_bits
)
49 /* The core treats 0 as 1 */
65 static void regmap_mmio_write8(struct regmap_mmio_context
*ctx
,
69 writeb(val
, ctx
->regs
+ reg
);
72 static void regmap_mmio_write8_relaxed(struct regmap_mmio_context
*ctx
,
76 writeb_relaxed(val
, ctx
->regs
+ reg
);
79 static void regmap_mmio_iowrite8(struct regmap_mmio_context
*ctx
,
80 unsigned int reg
, unsigned int val
)
82 iowrite8(val
, ctx
->regs
+ reg
);
85 static void regmap_mmio_write16le(struct regmap_mmio_context
*ctx
,
89 writew(val
, ctx
->regs
+ reg
);
92 static void regmap_mmio_write16le_relaxed(struct regmap_mmio_context
*ctx
,
96 writew_relaxed(val
, ctx
->regs
+ reg
);
99 static void regmap_mmio_iowrite16le(struct regmap_mmio_context
*ctx
,
100 unsigned int reg
, unsigned int val
)
102 iowrite16(val
, ctx
->regs
+ reg
);
105 static void regmap_mmio_write16be(struct regmap_mmio_context
*ctx
,
109 writew(swab16(val
), ctx
->regs
+ reg
);
112 static void regmap_mmio_iowrite16be(struct regmap_mmio_context
*ctx
,
113 unsigned int reg
, unsigned int val
)
115 iowrite16be(val
, ctx
->regs
+ reg
);
118 static void regmap_mmio_write32le(struct regmap_mmio_context
*ctx
,
122 writel(val
, ctx
->regs
+ reg
);
125 static void regmap_mmio_write32le_relaxed(struct regmap_mmio_context
*ctx
,
129 writel_relaxed(val
, ctx
->regs
+ reg
);
132 static void regmap_mmio_iowrite32le(struct regmap_mmio_context
*ctx
,
133 unsigned int reg
, unsigned int val
)
135 iowrite32(val
, ctx
->regs
+ reg
);
138 static void regmap_mmio_write32be(struct regmap_mmio_context
*ctx
,
142 writel(swab32(val
), ctx
->regs
+ reg
);
145 static void regmap_mmio_iowrite32be(struct regmap_mmio_context
*ctx
,
146 unsigned int reg
, unsigned int val
)
148 iowrite32be(val
, ctx
->regs
+ reg
);
151 static int regmap_mmio_write(void *context
, unsigned int reg
, unsigned int val
)
153 struct regmap_mmio_context
*ctx
= context
;
156 if (!IS_ERR(ctx
->clk
)) {
157 ret
= clk_enable(ctx
->clk
);
162 ctx
->reg_write(ctx
, reg
, val
);
164 if (!IS_ERR(ctx
->clk
))
165 clk_disable(ctx
->clk
);
170 static int regmap_mmio_noinc_write(void *context
, unsigned int reg
,
171 const void *val
, size_t val_count
)
173 struct regmap_mmio_context
*ctx
= context
;
177 if (!IS_ERR(ctx
->clk
)) {
178 ret
= clk_enable(ctx
->clk
);
184 * There are no native, assembly-optimized write single register
185 * operations for big endian, so fall back to emulation if this
186 * is needed. (Single bytes are fine, they are not affected by
189 if (ctx
->big_endian
&& (ctx
->val_bytes
> 1)) {
190 switch (ctx
->val_bytes
) {
193 const u16
*valp
= (const u16
*)val
;
194 for (i
= 0; i
< val_count
; i
++)
195 writew(swab16(valp
[i
]), ctx
->regs
+ reg
);
200 const u32
*valp
= (const u32
*)val
;
201 for (i
= 0; i
< val_count
; i
++)
202 writel(swab32(valp
[i
]), ctx
->regs
+ reg
);
211 switch (ctx
->val_bytes
) {
213 writesb(ctx
->regs
+ reg
, (const u8
*)val
, val_count
);
216 writesw(ctx
->regs
+ reg
, (const u16
*)val
, val_count
);
219 writesl(ctx
->regs
+ reg
, (const u32
*)val
, val_count
);
227 if (!IS_ERR(ctx
->clk
))
228 clk_disable(ctx
->clk
);
233 static unsigned int regmap_mmio_read8(struct regmap_mmio_context
*ctx
,
236 return readb(ctx
->regs
+ reg
);
239 static unsigned int regmap_mmio_read8_relaxed(struct regmap_mmio_context
*ctx
,
242 return readb_relaxed(ctx
->regs
+ reg
);
245 static unsigned int regmap_mmio_ioread8(struct regmap_mmio_context
*ctx
,
248 return ioread8(ctx
->regs
+ reg
);
251 static unsigned int regmap_mmio_read16le(struct regmap_mmio_context
*ctx
,
254 return readw(ctx
->regs
+ reg
);
257 static unsigned int regmap_mmio_read16le_relaxed(struct regmap_mmio_context
*ctx
,
260 return readw_relaxed(ctx
->regs
+ reg
);
263 static unsigned int regmap_mmio_ioread16le(struct regmap_mmio_context
*ctx
,
266 return ioread16(ctx
->regs
+ reg
);
269 static unsigned int regmap_mmio_read16be(struct regmap_mmio_context
*ctx
,
272 return swab16(readw(ctx
->regs
+ reg
));
275 static unsigned int regmap_mmio_ioread16be(struct regmap_mmio_context
*ctx
,
278 return ioread16be(ctx
->regs
+ reg
);
281 static unsigned int regmap_mmio_read32le(struct regmap_mmio_context
*ctx
,
284 return readl(ctx
->regs
+ reg
);
287 static unsigned int regmap_mmio_read32le_relaxed(struct regmap_mmio_context
*ctx
,
290 return readl_relaxed(ctx
->regs
+ reg
);
293 static unsigned int regmap_mmio_ioread32le(struct regmap_mmio_context
*ctx
,
296 return ioread32(ctx
->regs
+ reg
);
299 static unsigned int regmap_mmio_read32be(struct regmap_mmio_context
*ctx
,
302 return swab32(readl(ctx
->regs
+ reg
));
305 static unsigned int regmap_mmio_ioread32be(struct regmap_mmio_context
*ctx
,
308 return ioread32be(ctx
->regs
+ reg
);
311 static int regmap_mmio_read(void *context
, unsigned int reg
, unsigned int *val
)
313 struct regmap_mmio_context
*ctx
= context
;
316 if (!IS_ERR(ctx
->clk
)) {
317 ret
= clk_enable(ctx
->clk
);
322 *val
= ctx
->reg_read(ctx
, reg
);
324 if (!IS_ERR(ctx
->clk
))
325 clk_disable(ctx
->clk
);
330 static int regmap_mmio_noinc_read(void *context
, unsigned int reg
,
331 void *val
, size_t val_count
)
333 struct regmap_mmio_context
*ctx
= context
;
336 if (!IS_ERR(ctx
->clk
)) {
337 ret
= clk_enable(ctx
->clk
);
342 switch (ctx
->val_bytes
) {
344 readsb(ctx
->regs
+ reg
, (u8
*)val
, val_count
);
347 readsw(ctx
->regs
+ reg
, (u16
*)val
, val_count
);
350 readsl(ctx
->regs
+ reg
, (u32
*)val
, val_count
);
358 * There are no native, assembly-optimized write single register
359 * operations for big endian, so fall back to emulation if this
360 * is needed. (Single bytes are fine, they are not affected by
363 if (ctx
->big_endian
&& (ctx
->val_bytes
> 1)) {
364 switch (ctx
->val_bytes
) {
366 swab16_array(val
, val_count
);
369 swab32_array(val
, val_count
);
378 if (!IS_ERR(ctx
->clk
))
379 clk_disable(ctx
->clk
);
385 static void regmap_mmio_free_context(void *context
)
387 struct regmap_mmio_context
*ctx
= context
;
389 if (!IS_ERR(ctx
->clk
)) {
390 clk_unprepare(ctx
->clk
);
391 if (!ctx
->attached_clk
)
397 static const struct regmap_bus regmap_mmio
= {
399 .reg_write
= regmap_mmio_write
,
400 .reg_read
= regmap_mmio_read
,
401 .reg_noinc_write
= regmap_mmio_noinc_write
,
402 .reg_noinc_read
= regmap_mmio_noinc_read
,
403 .free_context
= regmap_mmio_free_context
,
404 .val_format_endian_default
= REGMAP_ENDIAN_LITTLE
,
407 static struct regmap_mmio_context
*regmap_mmio_gen_context(struct device
*dev
,
410 const struct regmap_config
*config
)
412 struct regmap_mmio_context
*ctx
;
416 ret
= regmap_mmio_regbits_check(config
->reg_bits
);
420 if (config
->pad_bits
)
421 return ERR_PTR(-EINVAL
);
423 min_stride
= regmap_mmio_get_min_stride(config
->val_bits
);
425 return ERR_PTR(min_stride
);
427 if (config
->reg_stride
&& config
->reg_stride
< min_stride
)
428 return ERR_PTR(-EINVAL
);
430 if (config
->use_relaxed_mmio
&& config
->io_port
)
431 return ERR_PTR(-EINVAL
);
433 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
435 return ERR_PTR(-ENOMEM
);
438 ctx
->val_bytes
= config
->val_bits
/ 8;
439 ctx
->clk
= ERR_PTR(-ENODEV
);
441 switch (regmap_get_val_endian(dev
, ®map_mmio
, config
)) {
442 case REGMAP_ENDIAN_DEFAULT
:
443 case REGMAP_ENDIAN_LITTLE
:
444 #ifdef __LITTLE_ENDIAN
445 case REGMAP_ENDIAN_NATIVE
:
447 switch (config
->val_bits
) {
449 if (config
->io_port
) {
450 ctx
->reg_read
= regmap_mmio_ioread8
;
451 ctx
->reg_write
= regmap_mmio_iowrite8
;
452 } else if (config
->use_relaxed_mmio
) {
453 ctx
->reg_read
= regmap_mmio_read8_relaxed
;
454 ctx
->reg_write
= regmap_mmio_write8_relaxed
;
456 ctx
->reg_read
= regmap_mmio_read8
;
457 ctx
->reg_write
= regmap_mmio_write8
;
461 if (config
->io_port
) {
462 ctx
->reg_read
= regmap_mmio_ioread16le
;
463 ctx
->reg_write
= regmap_mmio_iowrite16le
;
464 } else if (config
->use_relaxed_mmio
) {
465 ctx
->reg_read
= regmap_mmio_read16le_relaxed
;
466 ctx
->reg_write
= regmap_mmio_write16le_relaxed
;
468 ctx
->reg_read
= regmap_mmio_read16le
;
469 ctx
->reg_write
= regmap_mmio_write16le
;
473 if (config
->io_port
) {
474 ctx
->reg_read
= regmap_mmio_ioread32le
;
475 ctx
->reg_write
= regmap_mmio_iowrite32le
;
476 } else if (config
->use_relaxed_mmio
) {
477 ctx
->reg_read
= regmap_mmio_read32le_relaxed
;
478 ctx
->reg_write
= regmap_mmio_write32le_relaxed
;
480 ctx
->reg_read
= regmap_mmio_read32le
;
481 ctx
->reg_write
= regmap_mmio_write32le
;
489 case REGMAP_ENDIAN_BIG
:
491 case REGMAP_ENDIAN_NATIVE
:
493 ctx
->big_endian
= true;
494 switch (config
->val_bits
) {
496 if (config
->io_port
) {
497 ctx
->reg_read
= regmap_mmio_ioread8
;
498 ctx
->reg_write
= regmap_mmio_iowrite8
;
500 ctx
->reg_read
= regmap_mmio_read8
;
501 ctx
->reg_write
= regmap_mmio_write8
;
505 if (config
->io_port
) {
506 ctx
->reg_read
= regmap_mmio_ioread16be
;
507 ctx
->reg_write
= regmap_mmio_iowrite16be
;
509 ctx
->reg_read
= regmap_mmio_read16be
;
510 ctx
->reg_write
= regmap_mmio_write16be
;
514 if (config
->io_port
) {
515 ctx
->reg_read
= regmap_mmio_ioread32be
;
516 ctx
->reg_write
= regmap_mmio_iowrite32be
;
518 ctx
->reg_read
= regmap_mmio_read32be
;
519 ctx
->reg_write
= regmap_mmio_write32be
;
535 ctx
->clk
= clk_get(dev
, clk_id
);
536 if (IS_ERR(ctx
->clk
)) {
537 ret
= PTR_ERR(ctx
->clk
);
541 ret
= clk_prepare(ctx
->clk
);
555 struct regmap
*__regmap_init_mmio_clk(struct device
*dev
, const char *clk_id
,
557 const struct regmap_config
*config
,
558 struct lock_class_key
*lock_key
,
559 const char *lock_name
)
561 struct regmap_mmio_context
*ctx
;
563 ctx
= regmap_mmio_gen_context(dev
, clk_id
, regs
, config
);
565 return ERR_CAST(ctx
);
567 return __regmap_init(dev
, ®map_mmio
, ctx
, config
,
568 lock_key
, lock_name
);
570 EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk
);
572 struct regmap
*__devm_regmap_init_mmio_clk(struct device
*dev
,
575 const struct regmap_config
*config
,
576 struct lock_class_key
*lock_key
,
577 const char *lock_name
)
579 struct regmap_mmio_context
*ctx
;
581 ctx
= regmap_mmio_gen_context(dev
, clk_id
, regs
, config
);
583 return ERR_CAST(ctx
);
585 return __devm_regmap_init(dev
, ®map_mmio
, ctx
, config
,
586 lock_key
, lock_name
);
588 EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk
);
590 int regmap_mmio_attach_clk(struct regmap
*map
, struct clk
*clk
)
592 struct regmap_mmio_context
*ctx
= map
->bus_context
;
595 ctx
->attached_clk
= true;
597 return clk_prepare(ctx
->clk
);
599 EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk
);
601 void regmap_mmio_detach_clk(struct regmap
*map
)
603 struct regmap_mmio_context
*ctx
= map
->bus_context
;
605 clk_unprepare(ctx
->clk
);
607 ctx
->attached_clk
= false;
610 EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk
);
612 MODULE_LICENSE("GPL v2");