summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2020-04-16 18:40:49 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2020-04-16 18:40:49 +0200
commita1f5e9f895c704f068cf038bc05cbac6f7c9f310 (patch)
tree1d97a0993e8035d2137b1e5520b26a6c099b352d /drivers/base
parent32a48332753ac141998197f9f0e9c99d0d855102 (diff)
parent27d4a8f9a277ca362c7d6cecb53b65159c4bea10 (diff)
downloadbarebox-a1f5e9f895c704f068cf038bc05cbac6f7c9f310.tar.gz
barebox-a1f5e9f895c704f068cf038bc05cbac6f7c9f310.tar.xz
Merge branch 'for-next/spi'
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/internal.h4
-rw-r--r--drivers/base/regmap/regmap-mmio.c115
-rw-r--r--drivers/base/regmap/regmap.c44
3 files changed, 128 insertions, 35 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 5b19459828..4c7460fa4c 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -22,4 +22,8 @@ struct regmap {
struct cdev cdev;
};
+enum regmap_endian regmap_get_val_endian(struct device_d *dev,
+ const struct regmap_bus *bus,
+ const struct regmap_config *config);
+
#endif
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index f8d2cda843..7ca95d6bea 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -86,6 +86,20 @@ static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
writel(val, ctx->regs + reg);
}
+static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
+ unsigned int reg,
+ unsigned int val)
+{
+ iowrite16be(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
static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
unsigned int reg,
@@ -137,6 +151,18 @@ static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
}
#endif
+static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
+ unsigned int reg)
+{
+ return ioread16be(ctx->regs + reg);
+}
+
+static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
+ unsigned int reg)
+{
+ return ioread32be(ctx->regs + reg);
+}
+
static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
{
struct regmap_mmio_context *ctx = context;
@@ -156,9 +182,11 @@ static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
static const struct regmap_bus regmap_mmio = {
.reg_write = regmap_mmio_write,
.reg_read = regmap_mmio_read,
+ .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
};
-static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
+static struct regmap_mmio_context *regmap_mmio_gen_context(struct device_d *dev,
+ void __iomem *regs,
const struct regmap_config *config)
{
struct regmap_mmio_context *ctx;
@@ -184,18 +212,57 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
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;
+ switch (regmap_get_val_endian(dev, &regmap_mmio, config)) {
+ 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 32:
- ctx->reg_read = regmap_mmio_read32le;
- ctx->reg_write = regmap_mmio_write32le;
+ 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;
@@ -217,7 +284,7 @@ struct regmap *regmap_init_mmio_clk(struct device_d *dev,
{
struct regmap_mmio_context *ctx;
- ctx = regmap_mmio_gen_context(regs, config);
+ ctx = regmap_mmio_gen_context(dev, regs, config);
if (IS_ERR(ctx))
return ERR_CAST(ctx);
@@ -232,28 +299,6 @@ struct regmap *regmap_init_mmio_clk(struct device_d *dev,
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;
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index e3fa3896fe..6613670263 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -28,6 +28,50 @@
static LIST_HEAD(regmaps);
+enum regmap_endian regmap_get_val_endian(struct device_d *dev,
+ const struct regmap_bus *bus,
+ const struct regmap_config *config)
+{
+ struct device_node *np;
+ enum regmap_endian endian;
+
+ /* Retrieve the endianness specification from the regmap config */
+ endian = config->val_format_endian;
+
+ /* If the regmap config specified a non-default value, use that */
+ if (endian != REGMAP_ENDIAN_DEFAULT)
+ return endian;
+
+ /* If the dev and dev->device_node exist try to get endianness from DT */
+ if (dev && dev->device_node) {
+ np = dev->device_node;
+
+ /* Parse the device's DT node for an endianness specification */
+ if (of_property_read_bool(np, "big-endian"))
+ endian = REGMAP_ENDIAN_BIG;
+ else if (of_property_read_bool(np, "little-endian"))
+ endian = REGMAP_ENDIAN_LITTLE;
+ else if (of_property_read_bool(np, "native-endian"))
+ endian = REGMAP_ENDIAN_NATIVE;
+
+ /* If the endianness was specified in DT, use that */
+ if (endian != REGMAP_ENDIAN_DEFAULT)
+ return endian;
+ }
+
+ /* Retrieve the endianness specification from the bus config */
+ if (bus && bus->val_format_endian_default)
+ endian = bus->val_format_endian_default;
+
+ /* If the bus specified a non-default value, use that */
+ if (endian != REGMAP_ENDIAN_DEFAULT)
+ return endian;
+
+ /* Use this if no other value was found */
+ return REGMAP_ENDIAN_BIG;
+}
+EXPORT_SYMBOL_GPL(regmap_get_val_endian);
+
/*
* regmap_init - initialize and register a regmap
*