diff options
Diffstat (limited to 'drivers/base/regmap/regmap-mmio.c')
-rw-r--r-- | drivers/base/regmap/regmap-mmio.c | 259 |
1 files changed, 139 insertions, 120 deletions
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index eea51569f0eb..7526906ca080 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -25,26 +25,14 @@ struct regmap_mmio_context { void __iomem *regs; - unsigned reg_bytes; unsigned val_bytes; - unsigned pad_bytes; struct clk *clk; -}; -static inline void regmap_mmio_regsize_check(size_t reg_size) -{ - switch (reg_size) { - case 1: - case 2: - case 4: -#ifdef CONFIG_64BIT - case 8: -#endif - break; - default: - BUG(); - } -} + void (*reg_write)(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val); + unsigned int (*reg_read)(struct regmap_mmio_context *ctx, + unsigned int reg); +}; static int regmap_mmio_regbits_check(size_t reg_bits) { @@ -88,72 +76,62 @@ static int regmap_mmio_get_min_stride(size_t val_bits) return min_stride; } -static inline void regmap_mmio_count_check(size_t count, u32 offset) +static void regmap_mmio_write8(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeb(val, ctx->regs + reg); +} + +static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) { - BUG_ON(count <= offset); + writew(val, ctx->regs + reg); } -static inline unsigned int -regmap_mmio_get_offset(const void *reg, size_t reg_size) +static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) { - switch (reg_size) { - case 1: - return *(u8 *)reg; - case 2: - return *(u16 *)reg; - case 4: - return *(u32 *)reg; + iowrite16be(val, ctx->regs + reg); +} + +static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writel(val, ctx->regs + reg); +} + +static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + iowrite32be(val, ctx->regs + reg); +} + #ifdef CONFIG_64BIT - case 8: - return *(u64 *)reg; -#endif - default: - BUG(); - } +static void regmap_mmio_write64le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeq(val, ctx->regs + reg); } +#endif -static int regmap_mmio_gather_write(void *context, - const void *reg, size_t reg_size, - const void *val, size_t val_size) +static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) { struct regmap_mmio_context *ctx = context; - unsigned int offset; int ret; - regmap_mmio_regsize_check(reg_size); - if (!IS_ERR(ctx->clk)) { ret = clk_enable(ctx->clk); if (ret < 0) return ret; } - offset = regmap_mmio_get_offset(reg, reg_size); - - while (val_size) { - switch (ctx->val_bytes) { - case 1: - writeb(*(u8 *)val, ctx->regs + offset); - break; - case 2: - writew(*(u16 *)val, ctx->regs + offset); - break; - case 4: - writel(*(u32 *)val, ctx->regs + offset); - break; -#ifdef CONFIG_64BIT - case 8: - writeq(*(u64 *)val, ctx->regs + offset); - break; -#endif - default: - /* Should be caught by regmap_mmio_check_config */ - BUG(); - } - val_size -= ctx->val_bytes; - val += ctx->val_bytes; - offset += ctx->val_bytes; - } + ctx->reg_write(ctx, reg, val); if (!IS_ERR(ctx->clk)) clk_disable(ctx->clk); @@ -161,59 +139,56 @@ static int regmap_mmio_gather_write(void *context, return 0; } -static int regmap_mmio_write(void *context, const void *data, size_t count) +static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, + unsigned int reg) { - struct regmap_mmio_context *ctx = context; - unsigned int offset = ctx->reg_bytes + ctx->pad_bytes; + return readb(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readw(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread16be(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readl(ctx->regs + reg); +} - regmap_mmio_count_check(count, offset); +static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread32be(ctx->regs + reg); +} - return regmap_mmio_gather_write(context, data, ctx->reg_bytes, - data + offset, count - offset); +#ifdef CONFIG_64BIT +static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readq(ctx->regs + reg); } +#endif -static int regmap_mmio_read(void *context, - const void *reg, size_t reg_size, - void *val, size_t val_size) +static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) { struct regmap_mmio_context *ctx = context; - unsigned int offset; int ret; - regmap_mmio_regsize_check(reg_size); - if (!IS_ERR(ctx->clk)) { ret = clk_enable(ctx->clk); if (ret < 0) return ret; } - offset = regmap_mmio_get_offset(reg, reg_size); - - while (val_size) { - switch (ctx->val_bytes) { - case 1: - *(u8 *)val = readb(ctx->regs + offset); - break; - case 2: - *(u16 *)val = readw(ctx->regs + offset); - break; - case 4: - *(u32 *)val = readl(ctx->regs + offset); - break; -#ifdef CONFIG_64BIT - case 8: - *(u64 *)val = readq(ctx->regs + offset); - break; -#endif - default: - /* Should be caught by regmap_mmio_check_config */ - BUG(); - } - val_size -= ctx->val_bytes; - val += ctx->val_bytes; - offset += ctx->val_bytes; - } + *val = ctx->reg_read(ctx, reg); if (!IS_ERR(ctx->clk)) clk_disable(ctx->clk); @@ -232,14 +207,11 @@ static void regmap_mmio_free_context(void *context) kfree(context); } -static struct regmap_bus regmap_mmio = { +static const struct regmap_bus regmap_mmio = { .fast_io = true, - .write = regmap_mmio_write, - .gather_write = regmap_mmio_gather_write, - .read = regmap_mmio_read, + .reg_write = regmap_mmio_write, + .reg_read = regmap_mmio_read, .free_context = regmap_mmio_free_context, - .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, - .val_format_endian_default = REGMAP_ENDIAN_NATIVE, }; static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, @@ -265,24 +237,71 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, if (config->reg_stride < min_stride) return ERR_PTR(-EINVAL); - switch (config->reg_format_endian) { - case REGMAP_ENDIAN_DEFAULT: - case REGMAP_ENDIAN_NATIVE: - break; - default: - return ERR_PTR(-EINVAL); - } - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return ERR_PTR(-ENOMEM); ctx->regs = regs; ctx->val_bytes = config->val_bits / 8; - ctx->reg_bytes = config->reg_bits / 8; - ctx->pad_bytes = config->pad_bits / 8; ctx->clk = ERR_PTR(-ENODEV); + switch (config->reg_format_endian) { + case REGMAP_ENDIAN_DEFAULT: + case REGMAP_ENDIAN_LITTLE: +#ifdef __LITTLE_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16le; + ctx->reg_write = regmap_mmio_write16le; + break; + case 32: + ctx->reg_read = regmap_mmio_read32le; + ctx->reg_write = regmap_mmio_write32le; + break; +#ifdef CONFIG_64BIT + case 64: + ctx->reg_read = regmap_mmio_read64le; + ctx->reg_write = regmap_mmio_write64le; + break; +#endif + default: + ret = -EINVAL; + goto err_free; + } + break; + case REGMAP_ENDIAN_BIG: +#ifdef __BIG_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16be; + ctx->reg_write = regmap_mmio_write16be; + break; + case 32: + ctx->reg_read = regmap_mmio_read32be; + ctx->reg_write = regmap_mmio_write32be; + break; + default: + ret = -EINVAL; + goto err_free; + } + break; + default: + ret = -EINVAL; + goto err_free; + } + if (clk_id == NULL) return ctx; |