mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 3/6] regmap: add support for regmap_init_mmio_clk
Date: Tue, 18 Feb 2020 15:23:02 +0100	[thread overview]
Message-ID: <20200218142305.26992-4-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20200218142305.26992-1-a.fatoum@pengutronix.de>

regmap-mmio is used in Linux for clocked memory mapped I/O regions.
Port it over, so we can more easily port drivers using it.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/base/regmap/Makefile      |   3 +-
 drivers/base/regmap/regmap-mmio.c | 271 ++++++++++++++++++++++++++++++
 include/regmap.h                  |  50 ++++++
 3 files changed, 323 insertions(+), 1 deletion(-)
 create mode 100644 drivers/base/regmap/regmap-mmio.c

diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index 4dc3d8c510ae..ab2387037d37 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -1 +1,2 @@
-obj-y	+= regmap.o
\ No newline at end of file
+obj-y	+= regmap.o
+obj-y	+= regmap-mmio.o
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
new file mode 100644
index 000000000000..f8d2cda84353
--- /dev/null
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Register map access API - MMIO support
+//
+// Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <io.h>
+#include <regmap.h>
+
+#include "internal.h"
+
+struct regmap_mmio_context {
+	void __iomem *regs;
+	unsigned val_bytes;
+
+	struct clk *clk;
+
+	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)
+{
+	switch (reg_bits) {
+	case 8:
+	case 16:
+	case 32:
+#ifdef CONFIG_64BIT
+	case 64:
+#endif
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int regmap_mmio_get_min_stride(size_t val_bits)
+{
+	int min_stride;
+
+	switch (val_bits) {
+	case 8:
+		/* The core treats 0 as 1 */
+		min_stride = 0;
+		return 0;
+	case 16:
+		min_stride = 2;
+		break;
+	case 32:
+		min_stride = 4;
+		break;
+#ifdef CONFIG_64BIT
+	case 64:
+		min_stride = 8;
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	return min_stride;
+}
+
+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)
+{
+	writew(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);
+}
+
+#ifdef CONFIG_64BIT
+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_write(void *context, unsigned int reg, unsigned int val)
+{
+	struct regmap_mmio_context *ctx = context;
+	int ret;
+
+	ret = clk_enable(ctx->clk);
+	if (ret < 0)
+		return ret;
+
+	ctx->reg_write(ctx, reg, val);
+
+	clk_disable(ctx->clk);
+
+	return 0;
+}
+
+static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
+				      unsigned int reg)
+{
+	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_read32le(struct regmap_mmio_context *ctx,
+				         unsigned int reg)
+{
+	return readl(ctx->regs + reg);
+}
+
+#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, unsigned int reg, unsigned int *val)
+{
+	struct regmap_mmio_context *ctx = context;
+	int ret;
+
+	ret = clk_enable(ctx->clk);
+	if (ret < 0)
+		return ret;
+
+	*val = ctx->reg_read(ctx, reg);
+
+	clk_disable(ctx->clk);
+
+	return 0;
+}
+
+static const struct regmap_bus regmap_mmio = {
+	.reg_write = regmap_mmio_write,
+	.reg_read = regmap_mmio_read,
+};
+
+static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
+					const struct regmap_config *config)
+{
+	struct regmap_mmio_context *ctx;
+	int min_stride;
+	int ret;
+
+	ret = regmap_mmio_regbits_check(config->reg_bits);
+	if (ret)
+		return ERR_PTR(ret);
+
+	if (config->pad_bits)
+		return ERR_PTR(-EINVAL);
+
+	min_stride = regmap_mmio_get_min_stride(config->val_bits);
+	if (min_stride < 0)
+		return ERR_PTR(min_stride);
+
+	if (config->reg_stride < min_stride)
+		return ERR_PTR(-EINVAL);
+
+	ctx = xzalloc(sizeof(*ctx));
+
+	ctx->regs = regs;
+	ctx->val_bytes = config->val_bits / 8;
+
+	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;
+	default:
+		ret = -EINVAL;
+		goto err_free;
+	}
+
+	return ctx;
+
+err_free:
+	kfree(ctx);
+
+	return ERR_PTR(ret);
+}
+
+struct regmap *regmap_init_mmio_clk(struct device_d *dev,
+				    const char *clk_id,
+				    void __iomem *regs,
+				    const struct regmap_config *config)
+{
+	struct regmap_mmio_context *ctx;
+
+	ctx = regmap_mmio_gen_context(regs, config);
+	if (IS_ERR(ctx))
+		return ERR_CAST(ctx);
+
+	if (clk_id) {
+		ctx->clk = clk_get(dev, clk_id);
+		if (IS_ERR(ctx->clk)) {
+			kfree(ctx);
+			return ERR_CAST(ctx->clk);
+		}
+	}
+
+	return regmap_init(dev, &regmap_mmio, ctx, config);
+}
+
+struct regmap *of_regmap_init_mmio_clk(struct device_node *np,
+				       const char *clk_id,
+				       void __iomem *regs,
+				       const struct regmap_config *config)
+{
+	struct regmap_mmio_context *ctx;
+
+	ctx = regmap_mmio_gen_context(regs, config);
+	if (IS_ERR(ctx))
+		return ERR_CAST(ctx);
+
+	if (clk_id) {
+		ctx->clk = of_clk_get_by_name(np, clk_id);
+		if (IS_ERR(ctx->clk)) {
+			kfree(ctx);
+			return ERR_CAST(ctx->clk);
+		}
+	}
+
+	return regmap_init(NULL, &regmap_mmio, ctx, config);
+}
+
+int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk)
+{
+	struct regmap_mmio_context *ctx = map->bus_context;
+
+	ctx->clk = clk;
+
+	return 0;
+}
+
+void regmap_mmio_detach_clk(struct regmap *map)
+{
+	struct regmap_mmio_context *ctx = map->bus_context;
+
+	ctx->clk = NULL;
+}
diff --git a/include/regmap.h b/include/regmap.h
index 049ac0210e43..48ec5b077e3d 100644
--- a/include/regmap.h
+++ b/include/regmap.h
@@ -44,6 +44,56 @@ struct regmap *regmap_init(struct device_d *dev,
 			     const struct regmap_bus *bus,
 			     void *bus_context,
 			     const struct regmap_config *config);
+
+struct clk;
+
+/**
+ * of_regmap_init_mmio_clk() - Initialise register map with register clock
+ *
+ * @np: Device node that will be interacted with
+ * @clk_id: register clock consumer ID
+ * @regs: Pointer to memory-mapped IO region
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *of_regmap_init_mmio_clk(struct device_node *np, const char *clk_id,
+				       void __iomem *regs,
+				       const struct regmap_config *config);
+
+/**
+ * regmap_init_mmio_clk() - Initialise register map with register clock
+ *
+ * @dev: Device that will be interacted with
+ * @clk_id: register clock consumer ID
+ * @regs: Pointer to memory-mapped IO region
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_mmio_clk(struct device_d *dev, const char *clk_id,
+				    void __iomem *regs,
+				    const struct regmap_config *config);
+
+/**
+ * regmap_init_mmio() - Initialise register map
+ *
+ * @dev: Device that will be interacted with
+ * @regs: Pointer to memory-mapped IO region
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+#define regmap_init_mmio(dev, regs, config)		\
+	regmap_init_mmio_clk(dev, NULL, regs, config)
+
+
+int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk);
+void regmap_mmio_detach_clk(struct regmap *map);
+
 void regmap_exit(struct regmap *map);
 
 struct regmap *dev_get_regmap(struct device_d *dev, const char *name);
-- 
2.25.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2020-02-18 14:23 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-18 14:22 [PATCH 0/6] ARM: stm32mp: fix Ethernet after dts/ update Ahmad Fatoum
2020-02-18 14:23 ` [PATCH 1/6] ARM: dts: stm32mp: align barebox dtsi name with upstream Ahmad Fatoum
2020-02-18 14:23 ` [PATCH 2/6] regmap: make internal.h a self-contained header Ahmad Fatoum
2020-02-18 14:23 ` Ahmad Fatoum [this message]
2020-02-18 14:23 ` [PATCH 4/6] mfd: syscon: use regmap-mmio as backend Ahmad Fatoum
2020-02-18 14:23 ` [PATCH 5/6] mfd: syscon: clock peripheral if specified in device tree Ahmad Fatoum
2020-02-18 14:23 ` [PATCH 6/6] net: designware: eqos: stm32: drop no longer needed syscfg-clk Ahmad Fatoum
2020-02-19  8:03 ` [PATCH 0/6] ARM: stm32mp: fix Ethernet after dts/ update Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200218142305.26992-4-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox