mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] Add regmap support
@ 2016-02-03 16:20 Sascha Hauer
  2016-02-03 16:20 ` [PATCH 1/4] bitops: Fix shift overflow in GENMASK macros Sascha Hauer
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Sascha Hauer @ 2016-02-03 16:20 UTC (permalink / raw)
  To: Barebox List

This series adds simple regmap support. It's overdue to have regmap
support in barebox since regmap can make register accesses far more
generic and convenient. More and more kernel code depends on it, so
here it is for barebox. Two drivers are switched over to regmap to
provide some users.

----------------------------------------------------------------
Sascha Hauer (3):
      Add initial regmap support
      mfd: mc13xxx: Switch to regmap support
      ARM: i.MX ocotp: Switch to regmap support

Steffen Trumtrar (1):
      bitops: Fix shift overflow in GENMASK macros

 arch/arm/mach-imx/ocotp.c      | 146 ++++++---------
 drivers/base/Makefile          |   1 +
 drivers/base/regmap/Makefile   |   1 +
 drivers/base/regmap/internal.h |  18 ++
 drivers/base/regmap/regmap.c   | 398 +++++++++++++++++++++++++++++++++++++++++
 drivers/mfd/mc13xxx.c          | 123 ++++++-------
 include/linux/bitops.h         |   7 +-
 include/regmap.h               |  62 +++++++
 8 files changed, 594 insertions(+), 162 deletions(-)
 create mode 100644 drivers/base/regmap/Makefile
 create mode 100644 drivers/base/regmap/internal.h
 create mode 100644 drivers/base/regmap/regmap.c
 create mode 100644 include/regmap.h

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] bitops: Fix shift overflow in GENMASK macros
  2016-02-03 16:20 [PATCH] Add regmap support Sascha Hauer
@ 2016-02-03 16:20 ` Sascha Hauer
  2016-02-03 16:20 ` [PATCH 2/4] Add initial regmap support Sascha Hauer
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2016-02-03 16:20 UTC (permalink / raw)
  To: Barebox List; +Cc: Steffen Trumtrar

From: Steffen Trumtrar <s.trumtrar@pengutronix.de>

Based on the original patch for linux:

	commit 00b4d9a14125f1e51874def2b9de6092e007412d
	Author: Maxime COQUELIN <maxime.coquelin@st.com>
	Date:   Thu Nov 6 10:54:19 2014

	On some 32 bits architectures, including x86, GENMASK(31, 0) returns 0
	instead of the expected ~0UL.

	This is the same on some 64 bits architectures with GENMASK_ULL(63, 0).

	This is due to an overflow in the shift operand, 1 << 32 for GENMASK,
	1 << 64 for GENMASK_ULL.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 include/linux/bitops.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index f3a740c..31345c2 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -18,8 +18,11 @@
  * position @h. For example
  * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
  */
-#define GENMASK(h, l)		(((U32_C(1) << ((h) - (l) + 1)) - 1) << (l))
-#define GENMASK_ULL(h, l)	(((U64_C(1) << ((h) - (l) + 1)) - 1) << (l))
+#define GENMASK(h, l) \
+	(((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
+
+#define GENMASK_ULL(h, l) \
+	(((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
 
 extern unsigned int __sw_hweight8(unsigned int w);
 extern unsigned int __sw_hweight16(unsigned int w);
-- 
2.7.0.rc3


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/4] Add initial regmap support
  2016-02-03 16:20 [PATCH] Add regmap support Sascha Hauer
  2016-02-03 16:20 ` [PATCH 1/4] bitops: Fix shift overflow in GENMASK macros Sascha Hauer
@ 2016-02-03 16:20 ` Sascha Hauer
  2016-02-03 16:20 ` [PATCH 3/4] mfd: mc13xxx: Switch to " Sascha Hauer
  2016-02-03 16:20 ` [PATCH 4/4] ARM: i.MX ocotp: " Sascha Hauer
  3 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2016-02-03 16:20 UTC (permalink / raw)
  To: Barebox List

This adds initial regmap support. Function prototypes are from
the Kernel, the implemention is mostly rewritten. Currently the
regmap support is limited to the bare minimum to get started.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/base/Makefile          |   1 +
 drivers/base/regmap/Makefile   |   1 +
 drivers/base/regmap/internal.h |  18 ++
 drivers/base/regmap/regmap.c   | 398 +++++++++++++++++++++++++++++++++++++++++
 include/regmap.h               |  62 +++++++
 5 files changed, 480 insertions(+)
 create mode 100644 drivers/base/regmap/Makefile
 create mode 100644 drivers/base/regmap/internal.h
 create mode 100644 drivers/base/regmap/regmap.c
 create mode 100644 include/regmap.h

diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index e1f1c7a..4bd4217 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -2,3 +2,4 @@ obj-y	+= bus.o
 obj-y	+= driver.o
 obj-y	+= platform.o
 obj-y	+= resource.o
+obj-y	+= regmap/
\ No newline at end of file
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
new file mode 100644
index 0000000..4dc3d8c
--- /dev/null
+++ b/drivers/base/regmap/Makefile
@@ -0,0 +1 @@
+obj-y	+= regmap.o
\ No newline at end of file
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
new file mode 100644
index 0000000..52df529
--- /dev/null
+++ b/drivers/base/regmap/internal.h
@@ -0,0 +1,18 @@
+
+#include <linux/list.h>
+
+struct regmap {
+	struct device_d *dev;
+	const struct regmap_bus *bus;
+	const char *name;
+	void *bus_context;
+	struct list_head list;
+	int reg_bits;
+	int reg_stride;
+	int pad_bits;
+	int val_bits;
+	int val_bytes;
+	unsigned int max_register;
+
+	struct cdev cdev;
+};
\ No newline at end of file
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
new file mode 100644
index 0000000..b626f9a
--- /dev/null
+++ b/drivers/base/regmap/regmap.c
@@ -0,0 +1,398 @@
+/*
+ * Register map access API
+ *
+ * Copyright 2016 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * based on Kernel code:
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <common.h>
+#include <regmap.h>
+#include <malloc.h>
+#include <linux/log2.h>
+
+#include "internal.h"
+
+static LIST_HEAD(regmaps);
+
+/*
+ * regmap_init - initialize and register a regmap
+ *
+ * @dev:         The device the new regmap belongs to
+ * @bus:         The regmap_bus providing read/write access to the map
+ * @bus_context: Context pointer for the bus ops
+ * @config:      Configuration options for this map
+ *
+ * Returns a pointer to the new map or a ERR_PTR value on failure
+ */
+struct regmap *regmap_init(struct device_d *dev,
+			     const struct regmap_bus *bus,
+			     void *bus_context,
+			     const struct regmap_config *config)
+{
+	struct regmap *map;
+
+	map = xzalloc(sizeof(*map));
+	map->dev = dev;
+	map->bus = bus;
+	map->name = config->name;
+	map->bus_context = bus_context;
+	map->reg_bits = config->reg_bits;
+	map->reg_stride = config->reg_stride;
+	if (!map->reg_stride)
+		map->reg_stride = 1;
+	map->pad_bits = config->pad_bits;
+	map->val_bits = config->val_bits;
+	map->val_bytes = DIV_ROUND_UP(config->val_bits, 8);
+	map->max_register = config->max_register;
+
+	list_add_tail(&map->list, &regmaps);
+
+	return map;
+}
+
+/*
+ * regmap_init - initialize and register a regmap
+ *
+ * @dev:         The device the maps is attached to
+ * @name:        Optional name for the map. If given it must match.
+ *
+ * Returns a pointer to the regmap or a ERR_PTR value on failure
+ */
+struct regmap *dev_get_regmap(struct device_d *dev, const char *name)
+{
+	struct regmap *map;
+
+	list_for_each_entry(map, &regmaps, list) {
+		if (map->dev != dev)
+			continue;
+		if (!name)
+			return map;
+		if (!strcmp(map->name, name))
+			return map;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+/*
+ * of_node_to_regmap - get a regmap from a device node
+ *
+ * node:         The device node
+ *
+ * Returns a pointer to the regmap or a ERR_PTR if the node has no
+ * regmap attached.
+ */
+struct regmap *of_node_to_regmap(struct device_node *node)
+{
+	struct regmap *map;
+
+	list_for_each_entry(map, &regmaps, list) {
+		if (map->dev->device_node == node)
+			return map;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+/*
+ * regmap_write - write a register in a map
+ *
+ * @map:	The map
+ * @reg:	The register offset of the register
+ * @val:	The value to be written
+ *
+ * Returns 0 for success or negative error code on failure
+ */
+int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
+{
+	return map->bus->reg_write(map->bus_context, reg, val);
+}
+
+/*
+ * regmap_write - read a register from a map
+ *
+ * @map:	The map
+ * @reg:	The register offset of the register
+ * @val:	pointer to value read
+ *
+ * Returns 0 for success or negative error code on failure
+ */
+int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
+{
+	return map->bus->reg_read(map->bus_context, reg, val);
+}
+
+/**
+ * regmap_bulk_read(): Read data from the device
+ *
+ * @map: Register map to read from
+ * @reg: First register to be read from
+ * @val: Pointer to store read value
+ * @val_len: Size of data to read
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
+		     size_t val_len)
+{
+	size_t val_bytes = map->val_bytes;
+	size_t val_count = val_len / val_bytes;
+	unsigned int v;
+	int ret, i;
+
+	if (val_len % val_bytes)
+		return -EINVAL;
+	if (!IS_ALIGNED(reg, map->reg_stride))
+		return -EINVAL;
+	if (val_count == 0)
+		return -EINVAL;
+
+	for (i = 0; i < val_count; i++) {
+		u32 *u32 = val;
+		u16 *u16 = val;
+		u8 *u8 = val;
+
+		ret = regmap_read(map, reg + (i * map->reg_stride), &v);
+		if (ret != 0)
+			goto out;
+
+		switch (map->val_bytes) {
+		case 4:
+			u32[i] = v;
+			break;
+		case 2:
+			u16[i] = v;
+			break;
+		case 1:
+			u8[i] = v;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+ out:
+	return ret;
+}
+
+/**
+ * regmap_bulk_write(): Write values to one or more registers
+ *
+ * @map: Register map to write to
+ * @reg: Initial register to write to
+ * @val: Block of data to be written, laid out for direct transmission to the
+ *       device
+ * @val_len: Length of data pointed to by val.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_bulk_write(struct regmap *map, unsigned int reg,
+		     const void *val, size_t val_len)
+{
+	size_t val_bytes = map->val_bytes;
+	size_t val_count = val_len / val_bytes;
+	int ret, i;
+
+	if (val_len % val_bytes)
+		return -EINVAL;
+	if (!IS_ALIGNED(reg, map->reg_stride))
+		return -EINVAL;
+	if (val_count == 0)
+		return -EINVAL;
+
+	for (i = 0; i < val_count; i++) {
+		unsigned int ival;
+
+		switch (val_bytes) {
+		case 1:
+			ival = *(u8 *)(val + (i * val_bytes));
+			break;
+		case 2:
+			ival = *(u16 *)(val + (i * val_bytes));
+			break;
+		case 4:
+			ival = *(u32 *)(val + (i * val_bytes));
+			break;
+		default:
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = regmap_write(map, reg + (i * map->reg_stride),
+				ival);
+		if (ret != 0)
+			goto out;
+	}
+
+ out:
+	return ret;
+}
+
+int regmap_get_val_bytes(struct regmap *map)
+{
+	return map->val_bytes;
+}
+
+int regmap_get_max_register(struct regmap *map)
+{
+	return map->max_register;
+}
+
+int regmap_get_reg_stride(struct regmap *map)
+{
+	return map->reg_stride;
+}
+
+static int regmap_round_val_bytes(struct regmap *map)
+{
+	int val_bytes;
+
+	val_bytes = roundup_pow_of_two(map->val_bits) >> 3;
+	if (!val_bytes)
+		val_bytes = 1;
+
+	return val_bytes;
+}
+
+static ssize_t regmap_cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset,
+		       unsigned long flags)
+{
+	struct regmap *map = container_of(cdev, struct regmap, cdev);
+	int val_bytes = regmap_round_val_bytes(map);
+	int n = count;
+	int err;
+	unsigned int ofs = offset;
+
+	if (n < val_bytes || ofs & (val_bytes - 1))
+		return -EINVAL;
+
+	ofs /= val_bytes;
+	ofs *= map->reg_stride;
+
+	while (n > 0) {
+		err = regmap_read(map, ofs, buf);
+		if (err)
+			return (ssize_t)err;
+		buf += val_bytes;
+		n -= val_bytes;
+		ofs += map->reg_stride;
+	}
+
+	return count;
+}
+
+static ssize_t regmap_cdev_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset,
+			unsigned long flags)
+{
+	struct regmap *map = container_of(cdev, struct regmap, cdev);
+	int val_bytes = regmap_round_val_bytes(map);
+	int n = count;
+	int err;
+	unsigned int ofs = offset;
+
+	if (n < val_bytes || ofs & (val_bytes - 1))
+		return -EINVAL;
+
+	ofs /= val_bytes;
+	ofs *= map->reg_stride;
+
+	while (n > 0) {
+		u32 val;
+
+		switch (val_bytes) {
+		case 1:
+			val = *(u8 *)buf;
+			break;
+		case 2:
+			val = *(u16 *)buf;
+			break;
+		case 4:
+			val = *(u32 *)buf;
+			break;
+		default:
+			return -EINVAL;
+		};
+
+		err = regmap_write(map, ofs, val);
+		if (err)
+			return (ssize_t)err;
+		buf += val_bytes;
+		n -= val_bytes;
+		ofs += map->reg_stride;
+	}
+
+	return count;
+}
+
+static struct file_operations regmap_fops = {
+	.lseek	= dev_lseek_default,
+	.read	= regmap_cdev_read,
+	.write	= regmap_cdev_write,
+};
+
+/*
+ * regmap_register_cdev - register a devfs file for a regmap
+ *
+ * @map:	The map
+ * @name:	Optional name of the device file
+ *
+ * Returns 0 for success or negative error code on failure
+ */
+int regmap_register_cdev(struct regmap *map, const char *name)
+{
+	int ret;
+
+	if (map->cdev.name)
+		return -EBUSY;
+
+	if (!map->max_register)
+		return -EINVAL;
+
+	if (name) {
+		map->cdev.name = xstrdup(name);
+	} else {
+		if (map->name)
+			map->cdev.name = xasprintf("%s-%s", dev_name(map->dev), map->name);
+		else
+			map->cdev.name = xstrdup(dev_name(map->dev));
+	}
+
+	map->cdev.size = regmap_round_val_bytes(map) * (map->max_register + 1) /
+			map->reg_stride;
+	map->cdev.dev = map->dev;
+	map->cdev.ops = &regmap_fops;
+
+	ret = devfs_create(&map->cdev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+void regmap_exit(struct regmap *map)
+{
+	list_del(&map->list);
+
+	if (map->cdev.name) {
+		devfs_remove(&map->cdev);
+		free(map->cdev.name);
+	}
+
+	free(map);
+}
\ No newline at end of file
diff --git a/include/regmap.h b/include/regmap.h
new file mode 100644
index 0000000..4cb473c
--- /dev/null
+++ b/include/regmap.h
@@ -0,0 +1,62 @@
+#ifndef __REGMAP_H
+#define __REGMAP_H
+
+/**
+ * Configuration for the register map of a device.
+ *
+ * @name: Optional name of the regmap. Useful when a device has multiple
+ *        register regions.
+ *
+ * @reg_bits: Number of bits in a register address, mandatory.
+ * @reg_stride: The register address stride. Valid register addresses are a
+ *              multiple of this value. If set to 0, a value of 1 will be
+ *              used.
+ * @pad_bits: Number of bits of padding between register and value.
+ * @val_bits: Number of bits in a register value, mandatory.
+ *
+ * @max_register: Optional, specifies the maximum valid register index.
+ */
+struct regmap_config {
+	const char *name;
+
+	int reg_bits;
+	int reg_stride;
+	int pad_bits;
+	int val_bits;
+
+	unsigned int max_register;
+};
+
+typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg,
+				  unsigned int *val);
+typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg,
+				   unsigned int val);
+
+struct regmap_bus {
+	regmap_hw_reg_write reg_write;
+	regmap_hw_reg_read reg_read;
+};
+
+struct regmap *regmap_init(struct device_d *dev,
+			     const struct regmap_bus *bus,
+			     void *bus_context,
+			     const struct regmap_config *config);
+
+struct regmap *dev_get_regmap(struct device_d *dev, const char *name);
+struct regmap *of_node_to_regmap(struct device_node *node);
+
+int regmap_register_cdev(struct regmap *map, const char *name);
+
+int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
+int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
+
+int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
+		    size_t val_len);
+int regmap_bulk_write(struct regmap *map, unsigned int reg,
+		     const void *val, size_t val_len);
+
+int regmap_get_val_bytes(struct regmap *map);
+int regmap_get_max_register(struct regmap *map);
+int regmap_get_reg_stride(struct regmap *map);
+
+#endif /* __REGMAP_H */
\ No newline at end of file
-- 
2.7.0.rc3


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/4] mfd: mc13xxx: Switch to regmap support
  2016-02-03 16:20 [PATCH] Add regmap support Sascha Hauer
  2016-02-03 16:20 ` [PATCH 1/4] bitops: Fix shift overflow in GENMASK macros Sascha Hauer
  2016-02-03 16:20 ` [PATCH 2/4] Add initial regmap support Sascha Hauer
@ 2016-02-03 16:20 ` Sascha Hauer
  2016-02-03 16:20 ` [PATCH 4/4] ARM: i.MX ocotp: " Sascha Hauer
  3 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2016-02-03 16:20 UTC (permalink / raw)
  To: Barebox List

This moves the mc13xxx driver over to regmap.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mfd/mc13xxx.c | 123 +++++++++++++++++++++-----------------------------
 1 file changed, 52 insertions(+), 71 deletions(-)

diff --git a/drivers/mfd/mc13xxx.c b/drivers/mfd/mc13xxx.c
index 0ebfc9e..496fcbb 100644
--- a/drivers/mfd/mc13xxx.c
+++ b/drivers/mfd/mc13xxx.c
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <malloc.h>
 #include <of.h>
+#include <regmap.h>
 
 #include <i2c/i2c.h>
 #include <spi/spi.h>
@@ -29,15 +30,16 @@
 
 #define DRIVERNAME		"mc13xxx"
 
+#define MC13XXX_NUMREGS		0x3f
+
 struct mc13xxx {
-	struct cdev			cdev;
+	struct device_d			*dev;
+	struct regmap			*map;
 	union {
 		struct i2c_client	*client;
 		struct spi_device	*spi;
 	};
 	int				revision;
-	int				(*reg_read)(struct mc13xxx*, u8, u32*);
-	int				(*reg_write)(struct mc13xxx*, u8, u32);
 };
 
 struct mc13xxx_devtype {
@@ -100,8 +102,9 @@ static int spi_rw(struct spi_device *spi, void * buf, size_t len)
 #define MXC_PMIC_REG_NUM(reg)	(((reg) & 0x3f) << 25)
 #define MXC_PMIC_WRITE		(1 << 31)
 
-static int mc13xxx_spi_reg_read(struct mc13xxx *mc13xxx, u8 reg, u32 *val)
+static int mc13xxx_spi_reg_read(void *ctx, unsigned int reg, unsigned int *val)
 {
+	struct mc13xxx *mc13xxx = ctx;
 	uint32_t buf;
 
 	buf = MXC_PMIC_REG_NUM(reg);
@@ -113,8 +116,9 @@ static int mc13xxx_spi_reg_read(struct mc13xxx *mc13xxx, u8 reg, u32 *val)
 	return 0;
 }
 
-static int mc13xxx_spi_reg_write(struct mc13xxx *mc13xxx, u8 reg, u32 val)
+static int mc13xxx_spi_reg_write(void *ctx, unsigned int reg, unsigned int val)
 {
+	struct mc13xxx *mc13xxx = ctx;
 	uint32_t buf = MXC_PMIC_REG_NUM(reg) | MXC_PMIC_WRITE | (val & 0xffffff);
 
 	spi_rw(mc13xxx->spi, &buf, 4);
@@ -124,8 +128,9 @@ static int mc13xxx_spi_reg_write(struct mc13xxx *mc13xxx, u8 reg, u32 val)
 #endif
 
 #ifdef CONFIG_I2C
-static int mc13xxx_i2c_reg_read(struct mc13xxx *mc13xxx, u8 reg, u32 *val)
+static int mc13xxx_i2c_reg_read(void *ctx, unsigned int reg, unsigned int *val)
 {
+	struct mc13xxx *mc13xxx = ctx;
 	u8 buf[3];
 	int ret;
 
@@ -135,8 +140,9 @@ static int mc13xxx_i2c_reg_read(struct mc13xxx *mc13xxx, u8 reg, u32 *val)
 	return ret == 3 ? 0 : ret;
 }
 
-static int mc13xxx_i2c_reg_write(struct mc13xxx *mc13xxx, u8 reg, u32 val)
+static int mc13xxx_i2c_reg_write(void *ctx, unsigned int reg, unsigned int val)
 {
+	struct mc13xxx *mc13xxx = ctx;
 	u8 buf[] = {
 		val >> 16,
 		val >>  8,
@@ -152,13 +158,13 @@ static int mc13xxx_i2c_reg_write(struct mc13xxx *mc13xxx, u8 reg, u32 val)
 
 int mc13xxx_reg_write(struct mc13xxx *mc13xxx, u8 reg, u32 val)
 {
-	return mc13xxx->reg_write(mc13xxx, reg, val);
+	return regmap_write(mc13xxx->map, reg, val);
 }
 EXPORT_SYMBOL(mc13xxx_reg_write);
 
 int mc13xxx_reg_read(struct mc13xxx *mc13xxx, u8 reg, u32 *val)
 {
-	return mc13xxx->reg_read(mc13xxx, reg, val);
+	return regmap_read(mc13xxx->map, reg, val);
 }
 EXPORT_SYMBOL(mc13xxx_reg_read);
 
@@ -177,54 +183,6 @@ int mc13xxx_set_bits(struct mc13xxx *mc13xxx, u8 reg, u32 mask, u32 val)
 }
 EXPORT_SYMBOL(mc13xxx_set_bits);
 
-static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags)
-{
-	struct mc13xxx *mc13xxx = to_mc13xxx(cdev);
-	u32 *buf = _buf;
-	size_t i = count >> 2;
-	int err;
-
-	offset >>= 2;
-
-	while (i) {
-		err = mc13xxx_reg_read(mc13xxx, offset, buf);
-		if (err)
-			return (ssize_t)err;
-		buf++;
-		i--;
-		offset++;
-	}
-
-	return count;
-}
-
-static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags)
-{
-	struct mc13xxx *mc13xxx = to_mc13xxx(cdev);
-	const u32 *buf = _buf;
-	size_t i = count >> 2;
-	int err;
-
-	offset >>= 2;
-
-	while (i) {
-		err = mc13xxx_reg_write(mc13xxx, offset, *buf);
-		if (err)
-			return (ssize_t)err;
-		buf++;
-		i--;
-		offset++;
-	}
-
-	return count;
-}
-
-static struct file_operations mc_fops = {
-	.lseek	= dev_lseek_default,
-	.read	= mc_read,
-	.write	= mc_write,
-};
-
 static int __init mc13783_revision(struct mc13xxx *mc13xxx)
 {
 	unsigned int rev_id;
@@ -245,7 +203,7 @@ static int __init mc13783_revision(struct mc13xxx *mc13xxx)
 	} else
 		sprintf(revstr, "%d.%d", rev / 0x10, rev % 10);
 
-	dev_info(mc_dev->cdev.dev, "Found MC13783 ID: 0x%06x [Rev: %s]\n",
+	dev_info(mc_dev->dev, "Found MC13783 ID: 0x%06x [Rev: %s]\n",
 		 rev_id, revstr);
 
 	return rev;
@@ -297,7 +255,7 @@ static int __init mc13892_revision(struct mc13xxx *mc13xxx)
 		}
 	}
 
-	dev_info(mc_dev->cdev.dev, "Found MC13892 ID: 0x%06x [Rev: %s]\n",
+	dev_info(mc_dev->dev, "Found MC13892 ID: 0x%06x [Rev: %s]\n",
 		 rev_id, revstr);
 
 	return rev;
@@ -312,11 +270,34 @@ static int __init mc34708_revision(struct mc13xxx *mc13xxx)
 	if (rev_id > 0xfff)
 		return -ENODEV;
 
-	dev_info(mc_dev->cdev.dev, "Found MC34708 ID: 0x%03x\n", rev_id);
+	dev_info(mc_dev->dev, "Found MC34708 ID: 0x%03x\n", rev_id);
 
 	return (int)rev_id;
 }
 
+static struct regmap_bus regmap_mc13xxx_spi_bus = {
+	.reg_write = mc13xxx_spi_reg_write,
+	.reg_read = mc13xxx_spi_reg_read,
+};
+
+static const struct regmap_config mc13xxx_regmap_spi_config = {
+	.reg_bits = 7,
+	.pad_bits = 1,
+	.val_bits = 24,
+	.max_register = MC13XXX_NUMREGS,
+};
+
+static struct regmap_bus regmap_mc13xxx_i2c_bus = {
+	.reg_write = mc13xxx_i2c_reg_write,
+	.reg_read = mc13xxx_i2c_reg_read,
+};
+
+static const struct regmap_config mc13xxx_regmap_i2c_config = {
+	.reg_bits = 8,
+	.val_bits = 24,
+	.max_register = MC13XXX_NUMREGS,
+};
+
 static int __init mc13xxx_probe(struct device_d *dev)
 {
 	struct mc13xxx_devtype *devtype;
@@ -330,13 +311,14 @@ static int __init mc13xxx_probe(struct device_d *dev)
 		return ret;
 
 	mc_dev = xzalloc(sizeof(*mc_dev));
-	mc_dev->cdev.name = DRIVERNAME;
+	mc_dev->dev = dev;
 
 #ifdef CONFIG_I2C
 	if (dev->bus == &i2c_bus) {
 		mc_dev->client = to_i2c_client(dev);
-		mc_dev->reg_read = mc13xxx_i2c_reg_read;
-		mc_dev->reg_write = mc13xxx_i2c_reg_write;
+
+		mc_dev->map = regmap_init(dev, &regmap_mc13xxx_i2c_bus,
+			     mc_dev, &mc13xxx_regmap_i2c_config);
 	}
 #endif
 #ifdef CONFIG_SPI
@@ -345,25 +327,24 @@ static int __init mc13xxx_probe(struct device_d *dev)
 		mc_dev->spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
 		mc_dev->spi->bits_per_word = 32;
 		mc_dev->spi->max_speed_hz = 20000000;
-		mc_dev->reg_read = mc13xxx_spi_reg_read;
-		mc_dev->reg_write = mc13xxx_spi_reg_write;
+		mc_dev->map = regmap_init(dev, &regmap_mc13xxx_spi_bus,
+			     mc_dev, &mc13xxx_regmap_spi_config);
 	}
 #endif
 
-	mc_dev->cdev.size = 256;
-	mc_dev->cdev.dev = dev;
-	mc_dev->cdev.ops = &mc_fops;
-
 	rev = devtype->revision(mc_dev);
 	if (rev < 0) {
-		dev_err(mc_dev->cdev.dev, "No PMIC detected.\n");
+		dev_err(mc_dev->dev, "No PMIC detected.\n");
 		free(mc_dev);
 		mc_dev = NULL;
 		return rev;
 	}
 
 	mc_dev->revision = rev;
-	devfs_create(&mc_dev->cdev);
+
+	ret = regmap_register_cdev(mc_dev->map, NULL);
+	if (ret)
+		return ret;
 
 	if (mc13xxx_init_callback)
 		mc13xxx_init_callback(mc_dev);
-- 
2.7.0.rc3


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 4/4] ARM: i.MX ocotp: Switch to regmap support
  2016-02-03 16:20 [PATCH] Add regmap support Sascha Hauer
                   ` (2 preceding siblings ...)
  2016-02-03 16:20 ` [PATCH 3/4] mfd: mc13xxx: Switch to " Sascha Hauer
@ 2016-02-03 16:20 ` Sascha Hauer
  2016-02-04  7:38   ` Stefan Christ
  3 siblings, 1 reply; 7+ messages in thread
From: Sascha Hauer @ 2016-02-03 16:20 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/ocotp.c | 146 ++++++++++++++++++----------------------------
 1 file changed, 57 insertions(+), 89 deletions(-)

diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index c99a003..c6c341d 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -26,6 +26,7 @@
 #include <io.h>
 #include <of.h>
 #include <clock.h>
+#include <regmap.h>
 #include <linux/clk.h>
 
 /*
@@ -71,7 +72,7 @@
 #define MAC_BYTES			8
 
 struct ocotp_priv {
-	struct cdev cdev;
+	struct regmap *map;
 	void __iomem *base;
 	struct clk *clk;
 	struct device_d dev;
@@ -159,53 +160,42 @@ int imx6_ocotp_read_one_u32(u32 index, u32 *pdata, struct ocotp_priv *priv)
 
 	ret = imx6_ocotp_prepare(priv);
 	if (ret) {
-		dev_err(priv->cdev.dev, "failed to prepare read fuse 0x%08x\n",
+		dev_err(&priv->dev, "failed to prepare read fuse 0x%08x\n",
 				index);
 		return ret;
 	}
 
 	ret = fuse_read_addr(index, pdata, priv);
 	if (ret) {
-		dev_err(priv->cdev.dev, "failed to read fuse 0x%08x\n", index);
+		dev_err(&priv->dev, "failed to read fuse 0x%08x\n", index);
 		return ret;
 	}
 
 	if (readl(priv->base) & OCOTP_CTRL_ERROR) {
-		dev_err(priv->cdev.dev, "bad read status at fuse 0x%08x\n", index);
+		dev_err(&priv->dev, "bad read status at fuse 0x%08x\n", index);
 		return -EFAULT;
 	}
 
 	return 0;
 }
 
-static ssize_t imx6_ocotp_cdev_read(struct cdev *cdev, void *buf,
-		size_t count, loff_t offset, unsigned long flags)
+static int imx_ocotp_reg_read(void *ctx, unsigned int reg, unsigned int *val)
 {
+	struct ocotp_priv *priv = ctx;
 	u32 index;
-	ssize_t read_count = 0;
-	int ret, i;
-	struct ocotp_priv *priv = container_of(cdev, struct ocotp_priv, cdev);
-
-	index = offset >> 2;
-	count >>= 2;
-
-	if (count > (FUSE_REGS_COUNT - index))
-		count = FUSE_REGS_COUNT - index - 1;
-
-	for (i = index; i < (index + count); i++) {
-		if (priv->sense_enable) {
-			ret = imx6_ocotp_read_one_u32(i, buf, priv);
-			if (ret)
-				return ret;
-		} else {
-			*(u32 *)buf = readl(priv->base + 0x400 + i * 0x10);
-		}
+	int ret;
 
-		buf += 4;
-		read_count++;
+	index = reg >> 2;
+
+	if (priv->sense_enable) {
+		ret = imx6_ocotp_read_one_u32(index, val, priv);
+		if (ret)
+			return ret;
+	} else {
+		*(u32 *)val = readl(priv->base + 0x400 + index * 0x10);
 	}
 
-	return read_count << 2;
+	return 0;
 }
 
 static int fuse_blow_addr(u32 addr, u32 value, struct ocotp_priv *priv)
@@ -232,7 +222,7 @@ static int fuse_blow_addr(u32 addr, u32 value, struct ocotp_priv *priv)
 
 static int imx6_ocotp_reload_shadow(struct ocotp_priv *priv)
 {
-	dev_info(priv->cdev.dev, "reloading shadow registers...\n");
+	dev_info(&priv->dev, "reloading shadow registers...\n");
 	writel(OCOTP_CTRL_RELOAD_SHADOWS, priv->base + OCOTP_CTRL_SET);
 	udelay(1);
 
@@ -246,18 +236,18 @@ int imx6_ocotp_blow_one_u32(u32 index, u32 data, u32 *pfused_value,
 
 	ret = imx6_ocotp_prepare(priv);
 	if (ret) {
-		dev_err(priv->cdev.dev, "prepare to write failed\n");
+		dev_err(&priv->dev, "prepare to write failed\n");
 		return ret;
 	}
 
 	ret = fuse_blow_addr(index, data, priv);
 	if (ret) {
-		dev_err(priv->cdev.dev, "fuse blow failed\n");
+		dev_err(&priv->dev, "fuse blow failed\n");
 		return ret;
 	}
 
 	if (readl(priv->base) & OCOTP_CTRL_ERROR) {
-		dev_err(priv->cdev.dev, "bad write status\n");
+		dev_err(&priv->dev, "bad write status\n");
 		return -EFAULT;
 	}
 
@@ -266,60 +256,29 @@ int imx6_ocotp_blow_one_u32(u32 index, u32 data, u32 *pfused_value,
 	return ret;
 }
 
-static ssize_t imx6_ocotp_cdev_write(struct cdev *cdev, const void *buf,
-		size_t count, loff_t offset, unsigned long flags)
+static int imx_ocotp_reg_write(void *ctx, unsigned int reg, unsigned int val)
 {
-	struct ocotp_priv *priv = cdev->priv;
-	int index, i;
-	ssize_t write_count = 0;
-	const u32 *data;
+	struct ocotp_priv *priv = ctx;
+	int index;
 	u32 pfuse;
 	int ret;
 
-	/* We could do better, but currently this is what's implemented */
-	if (offset & 0x3 || count & 0x3) {
-		dev_err(cdev->dev, "only u32 aligned writes allowed\n");
-		return -EINVAL;
-	}
-
-	index = offset >> 2;
-	count >>= 2;
-
-	if (count > (FUSE_REGS_COUNT - index))
-		count = FUSE_REGS_COUNT - index - 1;
+	index = reg >> 2;
 
-	data = buf;
-
-	for (i = index; i < (index + count); i++) {
-		if (priv->permanent_write_enable) {
-			ret = imx6_ocotp_blow_one_u32(i, *data,
-					&pfuse, priv);
-			if (ret < 0) {
-				goto out;
-			}
-		} else {
-			writel(*data, priv->base + 0x400 + i * 0x10);
-		}
-
-		data++;
-		write_count++;
+	if (priv->permanent_write_enable) {
+		ret = imx6_ocotp_blow_one_u32(index, val, &pfuse, priv);
+		if (ret < 0)
+			return ret;
+	} else {
+		writel(val, priv->base + 0x400 + index * 0x10);
 	}
 
-	ret = 0;
-
-out:
 	if (priv->permanent_write_enable)
 		imx6_ocotp_reload_shadow(priv);
 
-	return ret < 0 ? ret : (write_count << 2);
+	return 0;
 }
 
-static struct file_operations imx6_ocotp_ops = {
-	.read	= imx6_ocotp_cdev_read,
-	.write	= imx6_ocotp_cdev_write,
-	.lseek	= dev_lseek_default,
-};
-
 static uint32_t inc_offset(uint32_t offset)
 {
 	if ((offset & 0x3) == 0x3)
@@ -373,9 +332,11 @@ static int imx_ocotp_get_mac(struct param_d *param, void *priv)
 {
 	struct ocotp_priv *ocotp_priv = priv;
 	char buf[8];
-	int i;
+	int i, ret;
 
-	imx6_ocotp_cdev_read(&ocotp_priv->cdev, buf, MAC_BYTES, MAC_OFFSET, 0);
+	ret = regmap_bulk_read(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES);
+	if (ret < 0)
+		return ret;
 
 	for (i = 0; i < 6; i++)
 		ocotp_priv->ethaddr[i] = buf[5 - i];
@@ -393,18 +354,29 @@ static int imx_ocotp_set_mac(struct param_d *param, void *priv)
 		buf[5 - i] = ocotp_priv->ethaddr[i];
 	buf[6] = 0; buf[7] = 0;
 
-	ret = imx6_ocotp_cdev_write(&ocotp_priv->cdev, buf, MAC_BYTES, MAC_OFFSET, 0);
+	ret = regmap_bulk_write(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES);
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
 
+static struct regmap_bus imx_ocotp_regmap_bus = {
+	.reg_write = imx_ocotp_reg_write,
+	.reg_read = imx_ocotp_reg_read,
+};
+
+static const struct regmap_config imx_ocotp_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0xbc,
+};
+
 static int imx_ocotp_probe(struct device_d *dev)
 {
 	void __iomem *base;
 	struct ocotp_priv *priv;
-	struct cdev *cdev;
 	int ret = 0;
 
 	base = dev_request_mem_region(dev, 0);
@@ -420,22 +392,18 @@ static int imx_ocotp_probe(struct device_d *dev)
 	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
 
-	cdev		= &priv->cdev;
-	cdev->dev	= dev;
-	cdev->ops	= &imx6_ocotp_ops;
-	cdev->priv	= priv;
-	cdev->size	= 192;
-	cdev->name	= "imx-ocotp";
-
-	ret = devfs_create(cdev);
-
-	if (ret < 0)
-		return ret;
-
 	strcpy(priv->dev.name, "ocotp");
 	priv->dev.parent = dev;
 	register_device(&priv->dev);
 
+	priv->map = regmap_init(dev, &imx_ocotp_regmap_bus, priv, &imx_ocotp_regmap_config);
+	if (IS_ERR(priv->map))
+		return PTR_ERR(priv->map);
+
+	ret = regmap_register_cdev(priv->map, "imx-ocotp");
+        if (ret)
+                return ret;
+
 	if (IS_ENABLED(CONFIG_IMX_OCOTP_WRITE)) {
 		dev_add_param_bool(&(priv->dev), "permanent_write_enable",
 				NULL, NULL, &priv->permanent_write_enable, NULL);
-- 
2.7.0.rc3


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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/4] ARM: i.MX ocotp: Switch to regmap support
  2016-02-03 16:20 ` [PATCH 4/4] ARM: i.MX ocotp: " Sascha Hauer
@ 2016-02-04  7:38   ` Stefan Christ
  2016-02-04  7:43     ` Sascha Hauer
  0 siblings, 1 reply; 7+ messages in thread
From: Stefan Christ @ 2016-02-04  7:38 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Barebox List

Hi Sascha,

> +	priv->map = regmap_init(dev, &imx_ocotp_regmap_bus, priv, &imx_ocotp_regmap_config);
> +	if (IS_ERR(priv->map))
> +		return PTR_ERR(priv->map);
> +
> +	ret = regmap_register_cdev(priv->map, "imx-ocotp");
> +        if (ret)
> +                return ret;
> +

Here are whitespaces instead of tabs.

Mit freundlichen Grüßen / Kind regards,
	Stefan Christ

On Wed, Feb 03, 2016 at 05:20:11PM +0100, Sascha Hauer wrote:
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm/mach-imx/ocotp.c | 146 ++++++++++++++++++----------------------------
>  1 file changed, 57 insertions(+), 89 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
> index c99a003..c6c341d 100644
> --- a/arch/arm/mach-imx/ocotp.c
> +++ b/arch/arm/mach-imx/ocotp.c
> @@ -26,6 +26,7 @@
>  #include <io.h>
>  #include <of.h>
>  #include <clock.h>
> +#include <regmap.h>
>  #include <linux/clk.h>
>  
>  /*
> @@ -71,7 +72,7 @@
>  #define MAC_BYTES			8
>  
>  struct ocotp_priv {
> -	struct cdev cdev;
> +	struct regmap *map;
>  	void __iomem *base;
>  	struct clk *clk;
>  	struct device_d dev;
> @@ -159,53 +160,42 @@ int imx6_ocotp_read_one_u32(u32 index, u32 *pdata, struct ocotp_priv *priv)
>  
>  	ret = imx6_ocotp_prepare(priv);
>  	if (ret) {
> -		dev_err(priv->cdev.dev, "failed to prepare read fuse 0x%08x\n",
> +		dev_err(&priv->dev, "failed to prepare read fuse 0x%08x\n",
>  				index);
>  		return ret;
>  	}
>  
>  	ret = fuse_read_addr(index, pdata, priv);
>  	if (ret) {
> -		dev_err(priv->cdev.dev, "failed to read fuse 0x%08x\n", index);
> +		dev_err(&priv->dev, "failed to read fuse 0x%08x\n", index);
>  		return ret;
>  	}
>  
>  	if (readl(priv->base) & OCOTP_CTRL_ERROR) {
> -		dev_err(priv->cdev.dev, "bad read status at fuse 0x%08x\n", index);
> +		dev_err(&priv->dev, "bad read status at fuse 0x%08x\n", index);
>  		return -EFAULT;
>  	}
>  
>  	return 0;
>  }
>  
> -static ssize_t imx6_ocotp_cdev_read(struct cdev *cdev, void *buf,
> -		size_t count, loff_t offset, unsigned long flags)
> +static int imx_ocotp_reg_read(void *ctx, unsigned int reg, unsigned int *val)
>  {
> +	struct ocotp_priv *priv = ctx;
>  	u32 index;
> -	ssize_t read_count = 0;
> -	int ret, i;
> -	struct ocotp_priv *priv = container_of(cdev, struct ocotp_priv, cdev);
> -
> -	index = offset >> 2;
> -	count >>= 2;
> -
> -	if (count > (FUSE_REGS_COUNT - index))
> -		count = FUSE_REGS_COUNT - index - 1;
> -
> -	for (i = index; i < (index + count); i++) {
> -		if (priv->sense_enable) {
> -			ret = imx6_ocotp_read_one_u32(i, buf, priv);
> -			if (ret)
> -				return ret;
> -		} else {
> -			*(u32 *)buf = readl(priv->base + 0x400 + i * 0x10);
> -		}
> +	int ret;
>  
> -		buf += 4;
> -		read_count++;
> +	index = reg >> 2;
> +
> +	if (priv->sense_enable) {
> +		ret = imx6_ocotp_read_one_u32(index, val, priv);
> +		if (ret)
> +			return ret;
> +	} else {
> +		*(u32 *)val = readl(priv->base + 0x400 + index * 0x10);
>  	}
>  
> -	return read_count << 2;
> +	return 0;
>  }
>  
>  static int fuse_blow_addr(u32 addr, u32 value, struct ocotp_priv *priv)
> @@ -232,7 +222,7 @@ static int fuse_blow_addr(u32 addr, u32 value, struct ocotp_priv *priv)
>  
>  static int imx6_ocotp_reload_shadow(struct ocotp_priv *priv)
>  {
> -	dev_info(priv->cdev.dev, "reloading shadow registers...\n");
> +	dev_info(&priv->dev, "reloading shadow registers...\n");
>  	writel(OCOTP_CTRL_RELOAD_SHADOWS, priv->base + OCOTP_CTRL_SET);
>  	udelay(1);
>  
> @@ -246,18 +236,18 @@ int imx6_ocotp_blow_one_u32(u32 index, u32 data, u32 *pfused_value,
>  
>  	ret = imx6_ocotp_prepare(priv);
>  	if (ret) {
> -		dev_err(priv->cdev.dev, "prepare to write failed\n");
> +		dev_err(&priv->dev, "prepare to write failed\n");
>  		return ret;
>  	}
>  
>  	ret = fuse_blow_addr(index, data, priv);
>  	if (ret) {
> -		dev_err(priv->cdev.dev, "fuse blow failed\n");
> +		dev_err(&priv->dev, "fuse blow failed\n");
>  		return ret;
>  	}
>  
>  	if (readl(priv->base) & OCOTP_CTRL_ERROR) {
> -		dev_err(priv->cdev.dev, "bad write status\n");
> +		dev_err(&priv->dev, "bad write status\n");
>  		return -EFAULT;
>  	}
>  
> @@ -266,60 +256,29 @@ int imx6_ocotp_blow_one_u32(u32 index, u32 data, u32 *pfused_value,
>  	return ret;
>  }
>  
> -static ssize_t imx6_ocotp_cdev_write(struct cdev *cdev, const void *buf,
> -		size_t count, loff_t offset, unsigned long flags)
> +static int imx_ocotp_reg_write(void *ctx, unsigned int reg, unsigned int val)
>  {
> -	struct ocotp_priv *priv = cdev->priv;
> -	int index, i;
> -	ssize_t write_count = 0;
> -	const u32 *data;
> +	struct ocotp_priv *priv = ctx;
> +	int index;
>  	u32 pfuse;
>  	int ret;
>  
> -	/* We could do better, but currently this is what's implemented */
> -	if (offset & 0x3 || count & 0x3) {
> -		dev_err(cdev->dev, "only u32 aligned writes allowed\n");
> -		return -EINVAL;
> -	}
> -
> -	index = offset >> 2;
> -	count >>= 2;
> -
> -	if (count > (FUSE_REGS_COUNT - index))
> -		count = FUSE_REGS_COUNT - index - 1;
> +	index = reg >> 2;
>  
> -	data = buf;
> -
> -	for (i = index; i < (index + count); i++) {
> -		if (priv->permanent_write_enable) {
> -			ret = imx6_ocotp_blow_one_u32(i, *data,
> -					&pfuse, priv);
> -			if (ret < 0) {
> -				goto out;
> -			}
> -		} else {
> -			writel(*data, priv->base + 0x400 + i * 0x10);
> -		}
> -
> -		data++;
> -		write_count++;
> +	if (priv->permanent_write_enable) {
> +		ret = imx6_ocotp_blow_one_u32(index, val, &pfuse, priv);
> +		if (ret < 0)
> +			return ret;
> +	} else {
> +		writel(val, priv->base + 0x400 + index * 0x10);
>  	}
>  
> -	ret = 0;
> -
> -out:
>  	if (priv->permanent_write_enable)
>  		imx6_ocotp_reload_shadow(priv);
>  
> -	return ret < 0 ? ret : (write_count << 2);
> +	return 0;
>  }
>  
> -static struct file_operations imx6_ocotp_ops = {
> -	.read	= imx6_ocotp_cdev_read,
> -	.write	= imx6_ocotp_cdev_write,
> -	.lseek	= dev_lseek_default,
> -};
> -
>  static uint32_t inc_offset(uint32_t offset)
>  {
>  	if ((offset & 0x3) == 0x3)
> @@ -373,9 +332,11 @@ static int imx_ocotp_get_mac(struct param_d *param, void *priv)
>  {
>  	struct ocotp_priv *ocotp_priv = priv;
>  	char buf[8];
> -	int i;
> +	int i, ret;
>  
> -	imx6_ocotp_cdev_read(&ocotp_priv->cdev, buf, MAC_BYTES, MAC_OFFSET, 0);
> +	ret = regmap_bulk_read(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES);
> +	if (ret < 0)
> +		return ret;
>  
>  	for (i = 0; i < 6; i++)
>  		ocotp_priv->ethaddr[i] = buf[5 - i];
> @@ -393,18 +354,29 @@ static int imx_ocotp_set_mac(struct param_d *param, void *priv)
>  		buf[5 - i] = ocotp_priv->ethaddr[i];
>  	buf[6] = 0; buf[7] = 0;
>  
> -	ret = imx6_ocotp_cdev_write(&ocotp_priv->cdev, buf, MAC_BYTES, MAC_OFFSET, 0);
> +	ret = regmap_bulk_write(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES);
>  	if (ret < 0)
>  		return ret;
>  
>  	return 0;
>  }
>  
> +static struct regmap_bus imx_ocotp_regmap_bus = {
> +	.reg_write = imx_ocotp_reg_write,
> +	.reg_read = imx_ocotp_reg_read,
> +};
> +
> +static const struct regmap_config imx_ocotp_regmap_config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = 0xbc,
> +};
> +
>  static int imx_ocotp_probe(struct device_d *dev)
>  {
>  	void __iomem *base;
>  	struct ocotp_priv *priv;
> -	struct cdev *cdev;
>  	int ret = 0;
>  
>  	base = dev_request_mem_region(dev, 0);
> @@ -420,22 +392,18 @@ static int imx_ocotp_probe(struct device_d *dev)
>  	if (IS_ERR(priv->clk))
>  		return PTR_ERR(priv->clk);
>  
> -	cdev		= &priv->cdev;
> -	cdev->dev	= dev;
> -	cdev->ops	= &imx6_ocotp_ops;
> -	cdev->priv	= priv;
> -	cdev->size	= 192;
> -	cdev->name	= "imx-ocotp";
> -
> -	ret = devfs_create(cdev);
> -
> -	if (ret < 0)
> -		return ret;
> -
>  	strcpy(priv->dev.name, "ocotp");
>  	priv->dev.parent = dev;
>  	register_device(&priv->dev);
>  
> +	priv->map = regmap_init(dev, &imx_ocotp_regmap_bus, priv, &imx_ocotp_regmap_config);
> +	if (IS_ERR(priv->map))
> +		return PTR_ERR(priv->map);
> +
> +	ret = regmap_register_cdev(priv->map, "imx-ocotp");
> +        if (ret)
> +                return ret;
> +
>  	if (IS_ENABLED(CONFIG_IMX_OCOTP_WRITE)) {
>  		dev_add_param_bool(&(priv->dev), "permanent_write_enable",
>  				NULL, NULL, &priv->permanent_write_enable, NULL);
> -- 
> 2.7.0.rc3
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/4] ARM: i.MX ocotp: Switch to regmap support
  2016-02-04  7:38   ` Stefan Christ
@ 2016-02-04  7:43     ` Sascha Hauer
  0 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2016-02-04  7:43 UTC (permalink / raw)
  To: Stefan Christ; +Cc: Barebox List

Hi Stefan,

On Thu, Feb 04, 2016 at 08:38:30AM +0100, Stefan Christ wrote:
> Hi Sascha,
> 
> > +	priv->map = regmap_init(dev, &imx_ocotp_regmap_bus, priv, &imx_ocotp_regmap_config);
> > +	if (IS_ERR(priv->map))
> > +		return PTR_ERR(priv->map);
> > +
> > +	ret = regmap_register_cdev(priv->map, "imx-ocotp");
> > +        if (ret)
> > +                return ret;
> > +
> 
> Here are whitespaces instead of tabs.

Fixed, thanks for noting

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-02-04  7:44 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-03 16:20 [PATCH] Add regmap support Sascha Hauer
2016-02-03 16:20 ` [PATCH 1/4] bitops: Fix shift overflow in GENMASK macros Sascha Hauer
2016-02-03 16:20 ` [PATCH 2/4] Add initial regmap support Sascha Hauer
2016-02-03 16:20 ` [PATCH 3/4] mfd: mc13xxx: Switch to " Sascha Hauer
2016-02-03 16:20 ` [PATCH 4/4] ARM: i.MX ocotp: " Sascha Hauer
2016-02-04  7:38   ` Stefan Christ
2016-02-04  7:43     ` Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox