Unverified Commit 77672e03 authored by Mark Brown's avatar Mark Brown
Browse files

regmap: mmio: Extending to support IO ports

Merge series from Andy Shevchenko <andriy.shevchenko@linux.intel.com>:

Currently regmap MMIO doesn't support IO ports, while being inconsistent
in used IO accessors. Fix the latter and extend framework with the
former.
parents 06000443 7e7ba58c
Loading
Loading
Loading
Loading
+88 −52
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
struct regmap_mmio_context {
	void __iomem *regs;
	unsigned int val_bytes;
	bool relaxed_mmio;

	bool attached_clk;
	struct clk *clk;
@@ -33,9 +32,6 @@ static int regmap_mmio_regbits_check(size_t reg_bits)
	case 8:
	case 16:
	case 32:
#ifdef CONFIG_64BIT
	case 64:
#endif
		return 0;
	default:
		return -EINVAL;
@@ -57,11 +53,6 @@ static int regmap_mmio_get_min_stride(size_t val_bits)
	case 32:
		min_stride = 4;
		break;
#ifdef CONFIG_64BIT
	case 64:
		min_stride = 8;
		break;
#endif
	default:
		return -EINVAL;
	}
@@ -83,6 +74,12 @@ static void regmap_mmio_write8_relaxed(struct regmap_mmio_context *ctx,
	writeb_relaxed(val, ctx->regs + reg);
}

static void regmap_mmio_iowrite8(struct regmap_mmio_context *ctx,
				 unsigned int reg, unsigned int val)
{
	iowrite8(val, ctx->regs + reg);
}

static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
				  unsigned int reg,
				  unsigned int val)
@@ -97,9 +94,21 @@ static void regmap_mmio_write16le_relaxed(struct regmap_mmio_context *ctx,
	writew_relaxed(val, ctx->regs + reg);
}

static void regmap_mmio_iowrite16le(struct regmap_mmio_context *ctx,
				    unsigned int reg, unsigned int val)
{
	iowrite16(val, ctx->regs + reg);
}

static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
				  unsigned int reg,
				  unsigned int val)
{
	writew(swab16(val), ctx->regs + reg);
}

static void regmap_mmio_iowrite16be(struct regmap_mmio_context *ctx,
				    unsigned int reg, unsigned int val)
{
	iowrite16be(val, ctx->regs + reg);
}
@@ -118,28 +127,24 @@ static void regmap_mmio_write32le_relaxed(struct regmap_mmio_context *ctx,
	writel_relaxed(val, ctx->regs + reg);
}

static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
				  unsigned int reg,
				  unsigned int val)
static void regmap_mmio_iowrite32le(struct regmap_mmio_context *ctx,
				    unsigned int reg, unsigned int val)
{
	iowrite32be(val, ctx->regs + reg);
	iowrite32(val, ctx->regs + reg);
}

#ifdef CONFIG_64BIT
static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
				  unsigned int reg,
				  unsigned int val)
{
	writeq(val, ctx->regs + reg);
	writel(swab32(val), ctx->regs + reg);
}

static void regmap_mmio_write64le_relaxed(struct regmap_mmio_context *ctx,
				  unsigned int reg,
				  unsigned int val)
static void regmap_mmio_iowrite32be(struct regmap_mmio_context *ctx,
				    unsigned int reg, unsigned int val)
{
	writeq_relaxed(val, ctx->regs + reg);
	iowrite32be(val, ctx->regs + reg);
}
#endif

static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
{
@@ -172,6 +177,12 @@ static unsigned int regmap_mmio_read8_relaxed(struct regmap_mmio_context *ctx,
	return readb_relaxed(ctx->regs + reg);
}

static unsigned int regmap_mmio_ioread8(struct regmap_mmio_context *ctx,
					unsigned int reg)
{
	return ioread8(ctx->regs + reg);
}

static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
				         unsigned int reg)
{
@@ -184,8 +195,20 @@ static unsigned int regmap_mmio_read16le_relaxed(struct regmap_mmio_context *ctx
	return readw_relaxed(ctx->regs + reg);
}

static unsigned int regmap_mmio_ioread16le(struct regmap_mmio_context *ctx,
					   unsigned int reg)
{
	return ioread16(ctx->regs + reg);
}

static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
				         unsigned int reg)
{
	return swab16(readw(ctx->regs + reg));
}

static unsigned int regmap_mmio_ioread16be(struct regmap_mmio_context *ctx,
					   unsigned int reg)
{
	return ioread16be(ctx->regs + reg);
}
@@ -202,25 +225,23 @@ static unsigned int regmap_mmio_read32le_relaxed(struct regmap_mmio_context *ctx
	return readl_relaxed(ctx->regs + reg);
}

static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
static unsigned int regmap_mmio_ioread32le(struct regmap_mmio_context *ctx,
					   unsigned int reg)
{
	return ioread32be(ctx->regs + reg);
	return ioread32(ctx->regs + reg);
}

#ifdef CONFIG_64BIT
static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
				         unsigned int reg)
{
	return readq(ctx->regs + reg);
	return swab32(readl(ctx->regs + reg));
}

static unsigned int regmap_mmio_read64le_relaxed(struct regmap_mmio_context *ctx,
static unsigned int regmap_mmio_ioread32be(struct regmap_mmio_context *ctx,
					   unsigned int reg)
{
	return readq_relaxed(ctx->regs + reg);
	return ioread32be(ctx->regs + reg);
}
#endif

static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
{
@@ -284,13 +305,15 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
	if (config->reg_stride < min_stride)
		return ERR_PTR(-EINVAL);

	if (config->use_relaxed_mmio && config->io_port)
		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->relaxed_mmio = config->use_relaxed_mmio;
	ctx->clk = ERR_PTR(-ENODEV);

	switch (regmap_get_val_endian(dev, &regmap_mmio, config)) {
@@ -301,7 +324,10 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
#endif
		switch (config->val_bits) {
		case 8:
			if (ctx->relaxed_mmio) {
			if (config->io_port) {
				ctx->reg_read = regmap_mmio_ioread8;
				ctx->reg_write = regmap_mmio_iowrite8;
			} else if (config->use_relaxed_mmio) {
				ctx->reg_read = regmap_mmio_read8_relaxed;
				ctx->reg_write = regmap_mmio_write8_relaxed;
			} else {
@@ -310,7 +336,10 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
			}
			break;
		case 16:
			if (ctx->relaxed_mmio) {
			if (config->io_port) {
				ctx->reg_read = regmap_mmio_ioread16le;
				ctx->reg_write = regmap_mmio_iowrite16le;
			} else if (config->use_relaxed_mmio) {
				ctx->reg_read = regmap_mmio_read16le_relaxed;
				ctx->reg_write = regmap_mmio_write16le_relaxed;
			} else {
@@ -319,7 +348,10 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
			}
			break;
		case 32:
			if (ctx->relaxed_mmio) {
			if (config->io_port) {
				ctx->reg_read = regmap_mmio_ioread32le;
				ctx->reg_write = regmap_mmio_iowrite32le;
			} else if (config->use_relaxed_mmio) {
				ctx->reg_read = regmap_mmio_read32le_relaxed;
				ctx->reg_write = regmap_mmio_write32le_relaxed;
			} else {
@@ -327,17 +359,6 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
				ctx->reg_write = regmap_mmio_write32le;
			}
			break;
#ifdef CONFIG_64BIT
		case 64:
			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:
			ret = -EINVAL;
			goto err_free;
@@ -349,16 +370,31 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
#endif
		switch (config->val_bits) {
		case 8:
			if (config->io_port) {
				ctx->reg_read = regmap_mmio_ioread8;
				ctx->reg_write = regmap_mmio_iowrite8;
			} else {
				ctx->reg_read = regmap_mmio_read8;
				ctx->reg_write = regmap_mmio_write8;
			}
			break;
		case 16:
			if (config->io_port) {
				ctx->reg_read = regmap_mmio_ioread16be;
				ctx->reg_write = regmap_mmio_iowrite16be;
			} else {
				ctx->reg_read = regmap_mmio_read16be;
				ctx->reg_write = regmap_mmio_write16be;
			}
			break;
		case 32:
			if (config->io_port) {
				ctx->reg_read = regmap_mmio_ioread32be;
				ctx->reg_write = regmap_mmio_iowrite32be;
			} else {
				ctx->reg_read = regmap_mmio_read32be;
				ctx->reg_write = regmap_mmio_write32be;
			}
			break;
		default:
			ret = -EINVAL;
+3 −0
Original line number Diff line number Diff line
@@ -311,6 +311,8 @@ typedef void (*regmap_unlock)(void *);
 *		  This field is a duplicate of a similar file in
 *		  'struct regmap_bus' and serves exact same purpose.
 *		   Use it only for "no-bus" cases.
 * @io_port:	  Support IO port accessors. Makes sense only when MMIO vs. IO port
 *		  access can be distinguished.
 * @max_register: Optional, specifies the maximum valid register address.
 * @wr_table:     Optional, points to a struct regmap_access_table specifying
 *                valid ranges for write access.
@@ -399,6 +401,7 @@ struct regmap_config {
	size_t max_raw_write;

	bool fast_io;
	bool io_port;

	unsigned int max_register;
	const struct regmap_access_table *wr_table;