diff options
author | Mark Brown <broonie@kernel.org> | 2020-11-30 18:16:06 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2020-11-30 18:16:06 +0000 |
commit | 4616c509d187d2afda4a8f1121c2a3ef16bbcefe (patch) | |
tree | 1db1557c8f8c789872cfc69523dc8fe6ec11f658 /drivers/base | |
parent | e6e9354b58307c120afbdc2719a6093638c37446 (diff) | |
parent | a8ecace132fa321f7fcc0650c4e486938a2a4bcb (diff) |
Merge remote-tracking branch 'regmap/for-5.11' into regmap-next
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/regmap/Kconfig | 6 | ||||
-rw-r--r-- | drivers/base/regmap/Makefile | 1 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-mmio.c | 90 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-sdw-mbq.c | 101 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-sdw.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 11 |
6 files changed, 198 insertions, 13 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index bcb90d8c3960..50b1e2d06a25 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -4,7 +4,7 @@ # subsystems should select the appropriate symbols. config REGMAP - default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM) + default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM) select IRQ_DOMAIN if REGMAP_IRQ bool @@ -46,6 +46,10 @@ config REGMAP_SOUNDWIRE tristate depends on SOUNDWIRE +config REGMAP_SOUNDWIRE_MBQ + tristate + depends on SOUNDWIRE + config REGMAP_SCCB tristate depends on I2C diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index ac1b69ee4051..33f63adb5b3d 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o obj-$(CONFIG_REGMAP_W1) += regmap-w1.o obj-$(CONFIG_REGMAP_SOUNDWIRE) += regmap-sdw.o +obj-$(CONFIG_REGMAP_SOUNDWIRE_MBQ) += regmap-sdw-mbq.o obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o obj-$(CONFIG_REGMAP_I3C) += regmap-i3c.o obj-$(CONFIG_REGMAP_SPI_AVMM) += regmap-spi-avmm.o diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index af967d8f975e..f9cd51afb9d2 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -16,6 +16,7 @@ struct regmap_mmio_context { void __iomem *regs; unsigned val_bytes; + bool relaxed_mmio; bool attached_clk; struct clk *clk; @@ -75,6 +76,13 @@ static void regmap_mmio_write8(struct regmap_mmio_context *ctx, writeb(val, ctx->regs + reg); } +static void regmap_mmio_write8_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeb_relaxed(val, ctx->regs + reg); +} + static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val) @@ -82,6 +90,13 @@ static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, writew(val, ctx->regs + reg); } +static void regmap_mmio_write16le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writew_relaxed(val, ctx->regs + reg); +} + static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val) @@ -96,6 +111,13 @@ static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, writel(val, ctx->regs + reg); } +static void regmap_mmio_write32le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writel_relaxed(val, ctx->regs + reg); +} + static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, unsigned int reg, unsigned int val) @@ -110,6 +132,13 @@ static void regmap_mmio_write64le(struct regmap_mmio_context *ctx, { writeq(val, ctx->regs + reg); } + +static void regmap_mmio_write64le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeq_relaxed(val, ctx->regs + reg); +} #endif static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) @@ -137,12 +166,24 @@ static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, return readb(ctx->regs + reg); } +static unsigned int regmap_mmio_read8_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readb_relaxed(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_read16le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readw_relaxed(ctx->regs + reg); +} + static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, unsigned int reg) { @@ -155,6 +196,12 @@ static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, return readl(ctx->regs + reg); } +static unsigned int regmap_mmio_read32le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readl_relaxed(ctx->regs + reg); +} + static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, unsigned int reg) { @@ -167,6 +214,12 @@ static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx, { return readq(ctx->regs + reg); } + +static unsigned int regmap_mmio_read64le_relaxed(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readq_relaxed(ctx->regs + reg); +} #endif static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) @@ -237,6 +290,7 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, ctx->regs = regs; ctx->val_bytes = config->val_bits / 8; + ctx->relaxed_mmio = config->use_relaxed_mmio; ctx->clk = ERR_PTR(-ENODEV); switch (regmap_get_val_endian(dev, ®map_mmio, config)) { @@ -247,21 +301,41 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, #endif switch (config->val_bits) { case 8: - ctx->reg_read = regmap_mmio_read8; - ctx->reg_write = regmap_mmio_write8; + if (ctx->relaxed_mmio) { + ctx->reg_read = regmap_mmio_read8_relaxed; + ctx->reg_write = regmap_mmio_write8_relaxed; + } else { + 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; + if (ctx->relaxed_mmio) { + ctx->reg_read = regmap_mmio_read16le_relaxed; + ctx->reg_write = regmap_mmio_write16le_relaxed; + } else { + 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; + if (ctx->relaxed_mmio) { + ctx->reg_read = regmap_mmio_read32le_relaxed; + ctx->reg_write = regmap_mmio_write32le_relaxed; + } else { + 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; + if (ctx->relaxed_mmio) { + ctx->reg_read = regmap_mmio_read64le_relaxed; + ctx->reg_write = regmap_mmio_write64le_relaxed; + } else { + ctx->reg_read = regmap_mmio_read64le; + ctx->reg_write = regmap_mmio_write64le; + } break; #endif default: diff --git a/drivers/base/regmap/regmap-sdw-mbq.c b/drivers/base/regmap/regmap-sdw-mbq.c new file mode 100644 index 000000000000..8ce30650b97c --- /dev/null +++ b/drivers/base/regmap/regmap-sdw-mbq.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright(c) 2020 Intel Corporation. + +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_registers.h> +#include "internal.h" + +static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val) +{ + struct device *dev = context; + struct sdw_slave *slave = dev_to_sdw_dev(dev); + int ret; + + ret = sdw_write(slave, SDW_SDCA_MBQ_CTL(reg), (val >> 8) & 0xff); + if (ret < 0) + return ret; + + return sdw_write(slave, reg, val & 0xff); +} + +static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *val) +{ + struct device *dev = context; + struct sdw_slave *slave = dev_to_sdw_dev(dev); + int read0; + int read1; + + read0 = sdw_read(slave, reg); + if (read0 < 0) + return read0; + + read1 = sdw_read(slave, SDW_SDCA_MBQ_CTL(reg)); + if (read1 < 0) + return read1; + + *val = (read1 << 8) | read0; + + return 0; +} + +static struct regmap_bus regmap_sdw_mbq = { + .reg_read = regmap_sdw_mbq_read, + .reg_write = regmap_sdw_mbq_write, + .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, + .val_format_endian_default = REGMAP_ENDIAN_LITTLE, +}; + +static int regmap_sdw_mbq_config_check(const struct regmap_config *config) +{ + /* MBQ-based controls are only 16-bits for now */ + if (config->val_bits != 16) + return -ENOTSUPP; + + /* Registers are 32 bits wide */ + if (config->reg_bits != 32) + return -ENOTSUPP; + + if (config->pad_bits != 0) + return -ENOTSUPP; + + return 0; +} + +struct regmap *__regmap_init_sdw_mbq(struct sdw_slave *sdw, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name) +{ + int ret; + + ret = regmap_sdw_mbq_config_check(config); + if (ret) + return ERR_PTR(ret); + + return __regmap_init(&sdw->dev, ®map_sdw_mbq, + &sdw->dev, config, lock_key, lock_name); +} +EXPORT_SYMBOL_GPL(__regmap_init_sdw_mbq); + +struct regmap *__devm_regmap_init_sdw_mbq(struct sdw_slave *sdw, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name) +{ + int ret; + + ret = regmap_sdw_mbq_config_check(config); + if (ret) + return ERR_PTR(ret); + + return __devm_regmap_init(&sdw->dev, ®map_sdw_mbq, + &sdw->dev, config, lock_key, lock_name); +} +EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw_mbq); + +MODULE_DESCRIPTION("Regmap SoundWire MBQ Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/base/regmap/regmap-sdw.c b/drivers/base/regmap/regmap-sdw.c index c92d614b4943..c83be26434e7 100644 --- a/drivers/base/regmap/regmap-sdw.c +++ b/drivers/base/regmap/regmap-sdw.c @@ -2,7 +2,9 @@ // Copyright(c) 2015-17 Intel Corporation. #include <linux/device.h> +#include <linux/errno.h> #include <linux/module.h> +#include <linux/regmap.h> #include <linux/soundwire/sdw.h> #include "internal.h" diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 5db536ccfcd6..297e95be25b3 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1924,12 +1924,15 @@ int _regmap_write(struct regmap *map, unsigned int reg, } } - if (regmap_should_log(map)) - dev_info(map->dev, "%x <= %x\n", reg, val); + ret = map->reg_write(context, reg, val); + if (ret == 0) { + if (regmap_should_log(map)) + dev_info(map->dev, "%x <= %x\n", reg, val); - trace_regmap_reg_write(map, reg, val); + trace_regmap_reg_write(map, reg, val); + } - return map->reg_write(context, reg, val); + return ret; } /** |