^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Register map access API - MMIO support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct regmap_mmio_context {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned val_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) bool attached_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) void (*reg_write)(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned int reg, unsigned int val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned int reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int regmap_mmio_regbits_check(size_t reg_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) switch (reg_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) case 64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int regmap_mmio_get_min_stride(size_t val_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int min_stride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) switch (val_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* The core treats 0 as 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) min_stride = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) min_stride = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) min_stride = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) case 64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) min_stride = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return min_stride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) writeb(val, ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) writew(val, ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) iowrite16be(val, ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) writel(val, ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) iowrite32be(val, ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) writeq(val, ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct regmap_mmio_context *ctx = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (!IS_ERR(ctx->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ret = clk_enable(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ctx->reg_write(ctx, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (!IS_ERR(ctx->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) clk_disable(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return readb(ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return readw(ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return ioread16be(ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return readl(ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return ioread32be(ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return readq(ctx->regs + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct regmap_mmio_context *ctx = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!IS_ERR(ctx->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ret = clk_enable(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) *val = ctx->reg_read(ctx, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!IS_ERR(ctx->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) clk_disable(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static void regmap_mmio_free_context(void *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct regmap_mmio_context *ctx = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (!IS_ERR(ctx->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) clk_unprepare(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (!ctx->attached_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) clk_put(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) kfree(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static const struct regmap_bus regmap_mmio = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .fast_io = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .reg_write = regmap_mmio_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .reg_read = regmap_mmio_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .free_context = regmap_mmio_free_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) const char *clk_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) void __iomem *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) const struct regmap_config *config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct regmap_mmio_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int min_stride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ret = regmap_mmio_regbits_check(config->reg_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (config->pad_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) min_stride = regmap_mmio_get_min_stride(config->val_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (min_stride < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return ERR_PTR(min_stride);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (config->reg_stride < min_stride)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ctx->regs = regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ctx->val_bytes = config->val_bits / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ctx->clk = ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) switch (regmap_get_val_endian(dev, ®map_mmio, config)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case REGMAP_ENDIAN_DEFAULT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case REGMAP_ENDIAN_LITTLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #ifdef __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case REGMAP_ENDIAN_NATIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) switch (config->val_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ctx->reg_read = regmap_mmio_read8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ctx->reg_write = regmap_mmio_write8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ctx->reg_read = regmap_mmio_read16le;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ctx->reg_write = regmap_mmio_write16le;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ctx->reg_read = regmap_mmio_read32le;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ctx->reg_write = regmap_mmio_write32le;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) case 64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ctx->reg_read = regmap_mmio_read64le;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ctx->reg_write = regmap_mmio_write64le;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) case REGMAP_ENDIAN_BIG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) case REGMAP_ENDIAN_NATIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) switch (config->val_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) ctx->reg_read = regmap_mmio_read8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ctx->reg_write = regmap_mmio_write8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ctx->reg_read = regmap_mmio_read16be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ctx->reg_write = regmap_mmio_write16be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ctx->reg_read = regmap_mmio_read32be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ctx->reg_write = regmap_mmio_write32be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (clk_id == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ctx->clk = clk_get(dev, clk_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (IS_ERR(ctx->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ret = PTR_ERR(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ret = clk_prepare(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) clk_put(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) kfree(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) void __iomem *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) const struct regmap_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct lock_class_key *lock_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) const char *lock_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct regmap_mmio_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (IS_ERR(ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return ERR_CAST(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return __regmap_init(dev, ®map_mmio, ctx, config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) lock_key, lock_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) const char *clk_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) void __iomem *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) const struct regmap_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct lock_class_key *lock_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) const char *lock_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct regmap_mmio_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (IS_ERR(ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return ERR_CAST(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return __devm_regmap_init(dev, ®map_mmio, ctx, config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) lock_key, lock_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct regmap_mmio_context *ctx = map->bus_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ctx->clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ctx->attached_clk = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return clk_prepare(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) void regmap_mmio_detach_clk(struct regmap *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct regmap_mmio_context *ctx = map->bus_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) clk_unprepare(ctx->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ctx->attached_clk = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) ctx->clk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) MODULE_LICENSE("GPL v2");