Devicetree
 help / color / mirror / Atom feed
* [PATCH v6 16/23] drivers/fsi: Add tracepoints for low-level operations
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, rostedt, mingo, gregkh, devicetree,
	linux-arm-kernel
  Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
	Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic@linux.vnet.ibm.com>

From: Jeremy Kerr <jk@ozlabs.org>

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Chris Bostic <cbostic@linux.vnet.ibm.com>
---
 drivers/fsi/fsi-core.c     |  27 +++++++---
 include/trace/events/fsi.h | 127 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 148 insertions(+), 6 deletions(-)
 create mode 100644 include/trace/events/fsi.h

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index f7e55e7..09becec 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -21,6 +21,9 @@
 
 #include "fsi-master.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/fsi.h>
+
 #define FSI_SLAVE_CONF_NEXT_MASK	0x80000000
 #define FSI_SLAVE_CONF_SLOTS_MASK	0x00ff0000
 #define FSI_SLAVE_CONF_SLOTS_SHIFT	16
@@ -541,11 +544,16 @@ static int fsi_master_read(struct fsi_master *master, int link,
 {
 	int rc;
 
+	trace_fsi_master_read(master, link, slave_id, addr, size);
+
 	rc = fsi_check_access(addr, size);
-	if (rc)
-		return rc;
+	if (!rc)
+		rc = master->read(master, link, slave_id, addr, val, size);
+
+	trace_fsi_master_rw_result(master, link, slave_id, addr, size,
+			false, val, rc);
 
-	return master->read(master, link, slave_id, addr, val, size);
+	return rc;
 }
 
 static int fsi_master_write(struct fsi_master *master, int link,
@@ -553,11 +561,16 @@ static int fsi_master_write(struct fsi_master *master, int link,
 {
 	int rc;
 
+	trace_fsi_master_write(master, link, slave_id, addr, size, val);
+
 	rc = fsi_check_access(addr, size);
-	if (rc)
-		return rc;
+	if (!rc)
+		rc = master->write(master, link, slave_id, addr, val, size);
 
-	return master->write(master, link, slave_id, addr, val, size);
+	trace_fsi_master_rw_result(master, link, slave_id, addr, size,
+			true, val, rc);
+
+	return rc;
 }
 
 static int fsi_master_link_enable(struct fsi_master *master, int link)
@@ -573,6 +586,8 @@ static int fsi_master_link_enable(struct fsi_master *master, int link)
  */
 static int fsi_master_break(struct fsi_master *master, int link)
 {
+	trace_fsi_master_break(master, link);
+
 	if (master->send_break)
 		return master->send_break(master, link);
 
diff --git a/include/trace/events/fsi.h b/include/trace/events/fsi.h
new file mode 100644
index 0000000..ac74a30
--- /dev/null
+++ b/include/trace/events/fsi.h
@@ -0,0 +1,127 @@
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM fsi
+
+#if !defined(_TRACE_FSI_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_FSI_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(fsi_master_read,
+	TP_PROTO(const struct fsi_master *master, int link, int id,
+			uint32_t addr, size_t size),
+	TP_ARGS(master, link, id, addr, size),
+	TP_STRUCT__entry(
+		__field(int,	master_idx)
+		__field(int,	link)
+		__field(int,	id)
+		__field(__u32,	addr)
+		__field(size_t,	size)
+	),
+	TP_fast_assign(
+		__entry->master_idx = master->idx;
+		__entry->link = link;
+		__entry->id = id;
+		__entry->addr = addr;
+		__entry->size = size;
+	),
+	TP_printk("fsi%d:%02d:%02d %08x[%zd]",
+		__entry->master_idx,
+		__entry->link,
+		__entry->id,
+		__entry->addr,
+		__entry->size
+	)
+);
+
+TRACE_EVENT(fsi_master_write,
+	TP_PROTO(const struct fsi_master *master, int link, int id,
+			uint32_t addr, size_t size, const void *data),
+	TP_ARGS(master, link, id, addr, size, data),
+	TP_STRUCT__entry(
+		__field(int,	master_idx)
+		__field(int,	link)
+		__field(int,	id)
+		__field(__u32,	addr)
+		__field(size_t,	size)
+		__field(__u32,	data)
+	),
+	TP_fast_assign(
+		__entry->master_idx = master->idx;
+		__entry->link = link;
+		__entry->id = id;
+		__entry->addr = addr;
+		__entry->size = size;
+		__entry->data = 0;
+		memcpy(&__entry->data, data, size);
+	),
+	TP_printk("fsi%d:%02d:%02d %08x[%zd] <= {%*ph}",
+		__entry->master_idx,
+		__entry->link,
+		__entry->id,
+		__entry->addr,
+		__entry->size,
+		__entry->size, &__entry->data
+	)
+);
+
+TRACE_EVENT(fsi_master_rw_result,
+	TP_PROTO(const struct fsi_master *master, int link, int id,
+			uint32_t addr, size_t size,
+			bool write, const void *data, int ret),
+	TP_ARGS(master, link, id, addr, size, write, data, ret),
+	TP_STRUCT__entry(
+		__field(int,	master_idx)
+		__field(int,	link)
+		__field(int,	id)
+		__field(__u32,	addr)
+		__field(size_t,	size)
+		__field(bool,	write)
+		__field(__u32,	data)
+		__field(int,	ret)
+	),
+	TP_fast_assign(
+		__entry->master_idx = master->idx;
+		__entry->link = link;
+		__entry->id = id;
+		__entry->addr = addr;
+		__entry->size = size;
+		__entry->write = write;
+		__entry->data = 0;
+		__entry->ret = ret;
+		if (__entry->write || !__entry->ret)
+			memcpy(&__entry->data, data, size);
+	),
+	TP_printk("fsi%d:%02d:%02d %08x[%zd] %s {%*ph} ret %d",
+		__entry->master_idx,
+		__entry->link,
+		__entry->id,
+		__entry->addr,
+		__entry->size,
+		__entry->write ? "<=" : "=>",
+		__entry->size, &__entry->data,
+		__entry->ret
+	)
+);
+
+TRACE_EVENT(fsi_master_break,
+	TP_PROTO(const struct fsi_master *master, int link),
+	TP_ARGS(master, link),
+	TP_STRUCT__entry(
+		__field(int,	master_idx)
+		__field(int,	link)
+	),
+	TP_fast_assign(
+		__entry->master_idx = master->idx;
+		__entry->link = link;
+	),
+	TP_printk("fsi%d:%d",
+		__entry->master_idx,
+		__entry->link
+	)
+);
+
+
+#endif /* _TRACE_FSI_H */
+
+#include <trace/define_trace.h>
-- 
1.8.2.2

^ permalink raw reply related

* [PATCH v6 15/23] drivers/fsi: expose direct-access slave API
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	mingo-H+wXaHxf7aLQT0dZR+AlfA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
	alistair-Y4h6yKqj69EXC2x5gXVKYQ,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>

Allow drivers to access the slave address ranges.

Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
 drivers/fsi/fsi-core.c | 26 ++++++++++++++++++++------
 include/linux/fsi.h    | 12 ++++++++++++
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index f0f0556..f7e55e7 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -76,10 +76,6 @@ static int fsi_master_read(struct fsi_master *master, int link,
 		uint8_t slave_id, uint32_t addr, void *val, size_t size);
 static int fsi_master_write(struct fsi_master *master, int link,
 		uint8_t slave_id, uint32_t addr, const void *val, size_t size);
-static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
-		void *val, size_t size);
-static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
-		const void *val, size_t size);
 
 /* FSI endpoint-device support */
 
@@ -181,7 +177,7 @@ static int fsi_slave_calc_addr(struct fsi_slave *slave, uint32_t *addrp,
 	return 0;
 }
 
-static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
+int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
 			void *val, size_t size)
 {
 	uint8_t id = slave->id;
@@ -195,7 +191,7 @@ static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
 			addr, val, size);
 }
 
-static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
+int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 			const void *val, size_t size)
 {
 	uint8_t id = slave->id;
@@ -209,6 +205,24 @@ static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 			addr, val, size);
 }
 
+extern int fsi_slave_claim_range(struct fsi_slave *slave,
+		uint32_t addr, uint32_t size)
+{
+	if (addr + size < addr)
+		return -EINVAL;
+
+	if (addr + size > slave->size)
+		return -EINVAL;
+
+	/* todo: check for overlapping claims */
+	return 0;
+}
+
+extern void fsi_slave_release_range(struct fsi_slave *slave,
+		uint32_t addr, uint32_t size)
+{
+}
+
 static int fsi_slave_scan(struct fsi_slave *slave)
 {
 	uint32_t engine_addr;
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index 34f1e9a..141fd38 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -66,6 +66,18 @@ struct fsi_driver {
 		module_driver(__fsi_driver, fsi_driver_register, \
 				fsi_driver_unregister)
 
+/* direct slave API */
+extern int fsi_slave_claim_range(struct fsi_slave *slave,
+		uint32_t addr, uint32_t size);
+extern void fsi_slave_release_range(struct fsi_slave *slave,
+		uint32_t addr, uint32_t size);
+extern int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
+		void *val, size_t size);
+extern int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
+		const void *val, size_t size);
+
+
+
 extern struct bus_type fsi_bus_type;
 
 #endif /* LINUX_FSI_H */
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v6 14/23] drivers/fsi: Add sysfs files for FSI master & slave accesses
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, rostedt, mingo, gregkh, devicetree,
	linux-arm-kernel
  Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
	Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic@linux.vnet.ibm.com>

From: Jeremy Kerr <jk@ozlabs.org>

This change adds a 'raw' file for reads & writes, and a 'term' file for
the TERM command, and a 'break' file for issuing a BREAK.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Chris Bostic <cbostic@linux.vnet.ibm.com>
---
 drivers/fsi/fsi-core.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 116 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 4359e26..f0f0556 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -294,6 +294,95 @@ static int fsi_slave_scan(struct fsi_slave *slave)
 	return 0;
 }
 
+static ssize_t fsi_slave_sysfs_raw_read(struct file *file,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct fsi_slave *slave = to_fsi_slave(kobj_to_dev(kobj));
+	size_t total_len, read_len;
+	int rc;
+
+	if (off < 0)
+		return -EINVAL;
+
+	if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
+		return -EINVAL;
+
+	for (total_len = 0; total_len < count; total_len += read_len) {
+		read_len = min_t(size_t, count, 4);
+		read_len -= off & 0x3;
+
+		rc = fsi_slave_read(slave, off, buf + total_len, read_len);
+		if (rc)
+			return rc;
+
+		off += read_len;
+	}
+
+	return count;
+}
+
+static ssize_t fsi_slave_sysfs_raw_write(struct file *file,
+		struct kobject *kobj, struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count)
+{
+	struct fsi_slave *slave = to_fsi_slave(kobj_to_dev(kobj));
+	size_t total_len, write_len;
+	int rc;
+
+	if (off < 0)
+		return -EINVAL;
+
+	if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
+		return -EINVAL;
+
+	for (total_len = 0; total_len < count; total_len += write_len) {
+		write_len = min_t(size_t, count, 4);
+		write_len -= off & 0x3;
+
+		rc = fsi_slave_write(slave, off, buf + total_len, write_len);
+		if (rc)
+			return rc;
+
+		off += write_len;
+	}
+
+	return count;
+}
+
+static struct bin_attribute fsi_slave_raw_attr = {
+	.attr = {
+		.name = "raw",
+		.mode = 0600,
+	},
+	.size = 0,
+	.read = fsi_slave_sysfs_raw_read,
+	.write = fsi_slave_sysfs_raw_write,
+};
+
+static ssize_t fsi_slave_sysfs_term_write(struct file *file,
+		struct kobject *kobj, struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count)
+{
+	struct fsi_slave *slave = to_fsi_slave(kobj_to_dev(kobj));
+	struct fsi_master *master = slave->master;
+
+	if (!master->term)
+		return -ENODEV;
+
+	master->term(master, slave->link, slave->id);
+	return count;
+}
+
+static struct bin_attribute fsi_slave_term_attr = {
+	.attr = {
+		.name = "term",
+		.mode = 0200,
+	},
+	.size = 0,
+	.write = fsi_slave_sysfs_term_write,
+};
+
 /* Encode slave local bus echo delay */
 static inline uint32_t fsi_smode_echodly(int x)
 {
@@ -409,6 +498,14 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 		return rc;
 	}
 
+	rc = device_create_bin_file(&slave->dev, &fsi_slave_raw_attr);
+	if (rc)
+		dev_warn(&slave->dev, "failed to create raw attr: %d\n", rc);
+
+	rc = device_create_bin_file(&slave->dev, &fsi_slave_term_attr);
+	if (rc)
+		dev_warn(&slave->dev, "failed to create term attr: %d\n", rc);
+
 	fsi_slave_scan(slave);
 	return 0;
 }
@@ -523,6 +620,18 @@ static ssize_t master_rescan_store(struct device *dev,
 
 static DEVICE_ATTR(rescan, 0200, NULL, master_rescan_store);
 
+static ssize_t master_break_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct fsi_master *master = to_fsi_master(dev);
+
+	fsi_master_break(master, 0);
+
+	return count;
+}
+
+static DEVICE_ATTR(break, 0200, NULL, master_break_store);
+
 int fsi_master_register(struct fsi_master *master)
 {
 	int rc;
@@ -546,6 +655,13 @@ int fsi_master_register(struct fsi_master *master)
 		return rc;
 	}
 
+	rc = device_create_file(&master->dev, &dev_attr_break);
+	if (rc) {
+		device_unregister(&master->dev);
+		ida_simple_remove(&master_ida, master->idx);
+		return rc;
+	}
+
 	fsi_master_scan(master);
 
 	return 0;
-- 
1.8.2.2

^ permalink raw reply related

* [PATCH v6 13/23] drivers/fsi: Add client driver register utilities
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	mingo-H+wXaHxf7aLQT0dZR+AlfA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Chris Bostic, joel-U3u1mxZcP9KHXe+LvDLADg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
	alistair-Y4h6yKqj69EXC2x5gXVKYQ,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r
In-Reply-To: <20170410194706.64280-1-cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

From: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

Add driver_register and driver_unregister wrappers for FSI.

Signed-off-by: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Signed-off-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
---
 drivers/fsi/fsi-core.c | 17 +++++++++++++++++
 include/linux/fsi.h    | 12 ++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 75d2a88..4359e26 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -585,6 +585,23 @@ static int fsi_bus_match(struct device *dev, struct device_driver *drv)
 	return 0;
 }
 
+int fsi_driver_register(struct fsi_driver *fsi_drv)
+{
+	if (!fsi_drv)
+		return -EINVAL;
+	if (!fsi_drv->id_table)
+		return -EINVAL;
+
+	return driver_register(&fsi_drv->drv);
+}
+EXPORT_SYMBOL_GPL(fsi_driver_register);
+
+void fsi_driver_unregister(struct fsi_driver *fsi_drv)
+{
+	driver_unregister(&fsi_drv->drv);
+}
+EXPORT_SYMBOL_GPL(fsi_driver_unregister);
+
 struct bus_type fsi_bus_type = {
 	.name		= "fsi",
 	.match		= fsi_bus_match,
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index 66bce48..34f1e9a 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -54,6 +54,18 @@ struct fsi_driver {
 #define to_fsi_dev(devp) container_of(devp, struct fsi_device, dev)
 #define to_fsi_drv(drvp) container_of(drvp, struct fsi_driver, drv)
 
+extern int fsi_driver_register(struct fsi_driver *fsi_drv);
+extern void fsi_driver_unregister(struct fsi_driver *fsi_drv);
+
+/* module_fsi_driver() - Helper macro for drivers that don't do
+ * anything special in module init/exit.  This eliminates a lot of
+ * boilerplate.  Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit()
+ */
+#define module_fsi_driver(__fsi_driver) \
+		module_driver(__fsi_driver, fsi_driver_register, \
+				fsi_driver_unregister)
+
 extern struct bus_type fsi_bus_type;
 
 #endif /* LINUX_FSI_H */
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v6 12/23] drivers/fsi: Add documentation for GPIO bindings
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, rostedt, mingo, gregkh, devicetree,
	linux-arm-kernel
  Cc: Chris Bostic, joel, linux-kernel, andrew, alistair, benh
In-Reply-To: <20170410194706.64280-1-cbostic@linux.vnet.ibm.com>

From: Chris Bostic <cbostic@linux.vnet.ibm.com>

Add fsi master gpio device tree binding documentation

Signed-off-by: Chris Bostic <cbostic@linux.vnet.ibm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/fsi/fsi-master-gpio.txt    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fsi/fsi-master-gpio.txt

diff --git a/Documentation/devicetree/bindings/fsi/fsi-master-gpio.txt b/Documentation/devicetree/bindings/fsi/fsi-master-gpio.txt
new file mode 100644
index 0000000..a767259
--- /dev/null
+++ b/Documentation/devicetree/bindings/fsi/fsi-master-gpio.txt
@@ -0,0 +1,24 @@
+Device-tree bindings for gpio-based FSI master driver
+-----------------------------------------------------
+
+Required properties:
+ - compatible = "fsi-master-gpio";
+ - clock-gpios = <gpio-descriptor>;	: GPIO for FSI clock
+ - data-gpios = <gpio-descriptor>;	: GPIO for FSI data signal
+
+Optional properties:
+ - enable-gpios = <gpio-descriptor>;	: GPIO for enable signal
+ - trans-gpios = <gpio-descriptor>;	: GPIO for voltage translator enable
+ - mux-gpios = <gpio-descriptor>;	: GPIO for pin multiplexing with other
+                                          functions (eg, external FSI masters)
+
+Examples:
+
+    fsi-master {
+        compatible = "fsi-master-gpio", "fsi-master";
+        clock-gpios = <&gpio 0>;
+        data-gpios = <&gpio 1>;
+        enable-gpios = <&gpio 2>;
+        trans-gpios = <&gpio 3>;
+        mux-gpios = <&gpio 4>;
+    }
-- 
1.8.2.2

^ permalink raw reply related

* [PATCH v6 11/23] drivers/fsi: Add master unscan
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	mingo-H+wXaHxf7aLQT0dZR+AlfA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Chris Bostic, joel-U3u1mxZcP9KHXe+LvDLADg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
	alistair-Y4h6yKqj69EXC2x5gXVKYQ,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r
In-Reply-To: <20170410194706.64280-1-cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

From: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

Allow a master to undo a previous scan.  Should a master scan a bus
twice it will need to ensure it doesn't double register any
previously detected device.

Signed-off-by: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Signed-off-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
---
 drivers/fsi/fsi-core.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 4da0b030..75d2a88 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -69,6 +69,7 @@ struct fsi_slave {
 	uint32_t		size;	/* size of slave address space */
 };
 
+#define to_fsi_master(d) container_of(d, struct fsi_master, dev)
 #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
 
 static int fsi_master_read(struct fsi_master *master, int link,
@@ -491,6 +492,37 @@ static int fsi_master_scan(struct fsi_master *master)
 	return 0;
 }
 
+static int __fsi_slave_remove_device(struct device *dev, void *arg)
+{
+	device_unregister(dev);
+	return 0;
+}
+
+static int __fsi_master_remove_slave(struct device *dev, void *arg)
+{
+	device_for_each_child(dev, NULL, __fsi_slave_remove_device);
+	device_unregister(dev);
+	return 0;
+}
+
+static void fsi_master_unscan(struct fsi_master *master)
+{
+	device_for_each_child(&master->dev, NULL, __fsi_master_remove_slave);
+}
+
+static ssize_t master_rescan_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct fsi_master *master = to_fsi_master(dev);
+
+	fsi_master_unscan(master);
+	fsi_master_scan(master);
+
+	return count;
+}
+
+static DEVICE_ATTR(rescan, 0200, NULL, master_rescan_store);
+
 int fsi_master_register(struct fsi_master *master)
 {
 	int rc;
@@ -507,7 +539,15 @@ int fsi_master_register(struct fsi_master *master)
 		return rc;
 	}
 
+	rc = device_create_file(&master->dev, &dev_attr_rescan);
+	if (rc) {
+		device_unregister(&master->dev);
+		ida_simple_remove(&master_ida, master->idx);
+		return rc;
+	}
+
 	fsi_master_scan(master);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(fsi_master_register);
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v6 10/23] drivers/fsi: Add device read/write/peek API
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	mingo-H+wXaHxf7aLQT0dZR+AlfA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
	alistair-Y4h6yKqj69EXC2x5gXVKYQ,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Edward A . James,
	Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>

This change introduces the fsi device API: simple read, write and peek
accessors for the devices' address spaces.

Includes contributions from Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
and Edward A. James <eajames-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>.

Signed-off-by: Edward A. James <eajames-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Signed-off-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
---
 drivers/fsi/fsi-core.c | 33 +++++++++++++++++++++++++++++++++
 include/linux/fsi.h    |  7 ++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index a8faa89..4da0b030 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -32,6 +32,8 @@
 #define FSI_SLAVE_CONF_CRC_MASK		0x0000000f
 #define FSI_SLAVE_CONF_DATA_BITS	28
 
+#define FSI_PEEK_BASE			0x410
+
 static const int engine_page_size = 0x400;
 
 #define FSI_SLAVE_BASE			0x800
@@ -73,9 +75,40 @@ static int fsi_master_read(struct fsi_master *master, int link,
 		uint8_t slave_id, uint32_t addr, void *val, size_t size);
 static int fsi_master_write(struct fsi_master *master, int link,
 		uint8_t slave_id, uint32_t addr, const void *val, size_t size);
+static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
+		void *val, size_t size);
+static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
+		const void *val, size_t size);
 
 /* FSI endpoint-device support */
 
+int fsi_device_read(struct fsi_device *dev, uint32_t addr, void *val,
+		size_t size)
+{
+	if (addr > dev->size || size > dev->size || addr > dev->size - size)
+		return -EINVAL;
+
+	return fsi_slave_read(dev->slave, dev->addr + addr, val, size);
+}
+EXPORT_SYMBOL_GPL(fsi_device_read);
+
+int fsi_device_write(struct fsi_device *dev, uint32_t addr, const void *val,
+		size_t size)
+{
+	if (addr > dev->size || size > dev->size || addr > dev->size - size)
+		return -EINVAL;
+
+	return fsi_slave_write(dev->slave, dev->addr + addr, val, size);
+}
+EXPORT_SYMBOL_GPL(fsi_device_write);
+
+int fsi_device_peek(struct fsi_device *dev, void *val)
+{
+	uint32_t addr = FSI_PEEK_BASE + ((dev->unit - 2) * sizeof(uint32_t));
+
+	return fsi_slave_read(dev->slave, addr, val, sizeof(uint32_t));
+}
+
 static void fsi_device_release(struct device *_device)
 {
 	struct fsi_device *device = to_fsi_dev(_device);
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index efa55ba..66bce48 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -27,6 +27,12 @@ struct fsi_device {
 	uint32_t		size;
 };
 
+extern int fsi_device_read(struct fsi_device *dev, uint32_t addr,
+		void *val, size_t size);
+extern int fsi_device_write(struct fsi_device *dev, uint32_t addr,
+		const void *val, size_t size);
+extern int fsi_device_peek(struct fsi_device *dev, void *val);
+
 struct fsi_device_id {
 	u8	engine_type;
 	u8	version;
@@ -40,7 +46,6 @@ struct fsi_device_id {
 #define FSI_DEVICE_VERSIONED(t, v) \
 	.engine_type = (t), .version = (v),
 
-
 struct fsi_driver {
 	struct device_driver		drv;
 	const struct fsi_device_id	*id_table;
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v6 09/23] drivers/fsi: scan slaves & register devices
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, rostedt, mingo, gregkh, devicetree,
	linux-arm-kernel
  Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
	Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic@linux.vnet.ibm.com>

From: Jeremy Kerr <jk@ozlabs.org>

Now that we have fsi_slave devices, scan each for endpoints, and
register them on the fsi bus.

Includes contributions from Chris Bostic <cbostic@linux.vnet.ibm.com>

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@linux.vnet.ibm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 drivers/fsi/fsi-core.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/fsi.h    |   4 ++
 2 files changed, 128 insertions(+), 3 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index b7b138b..a8faa89 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -21,6 +21,19 @@
 
 #include "fsi-master.h"
 
+#define FSI_SLAVE_CONF_NEXT_MASK	0x80000000
+#define FSI_SLAVE_CONF_SLOTS_MASK	0x00ff0000
+#define FSI_SLAVE_CONF_SLOTS_SHIFT	16
+#define FSI_SLAVE_CONF_VERSION_MASK	0x0000f000
+#define FSI_SLAVE_CONF_VERSION_SHIFT	12
+#define FSI_SLAVE_CONF_TYPE_MASK	0x00000ff0
+#define FSI_SLAVE_CONF_TYPE_SHIFT	4
+#define FSI_SLAVE_CONF_CRC_SHIFT	4
+#define FSI_SLAVE_CONF_CRC_MASK		0x0000000f
+#define FSI_SLAVE_CONF_DATA_BITS	28
+
+static const int engine_page_size = 0x400;
+
 #define FSI_SLAVE_BASE			0x800
 
 /*
@@ -61,6 +74,30 @@ static int fsi_master_read(struct fsi_master *master, int link,
 static int fsi_master_write(struct fsi_master *master, int link,
 		uint8_t slave_id, uint32_t addr, const void *val, size_t size);
 
+/* FSI endpoint-device support */
+
+static void fsi_device_release(struct device *_device)
+{
+	struct fsi_device *device = to_fsi_dev(_device);
+
+	kfree(device);
+}
+
+static struct fsi_device *fsi_create_device(struct fsi_slave *slave)
+{
+	struct fsi_device *dev;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->dev.parent = &slave->dev;
+	dev->dev.bus = &fsi_bus_type;
+	dev->dev.release = fsi_device_release;
+
+	return dev;
+}
+
 /* crc helpers */
 static const uint8_t crc4_tab[] = {
 	0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
@@ -138,6 +175,91 @@ static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 			addr, val, size);
 }
 
+static int fsi_slave_scan(struct fsi_slave *slave)
+{
+	uint32_t engine_addr;
+	uint32_t conf;
+	int rc, i;
+
+	/*
+	 * scan engines
+	 *
+	 * We keep the peek mode and slave engines for the core; so start
+	 * at the third slot in the configuration table. We also need to
+	 * skip the chip ID entry at the start of the address space.
+	 */
+	engine_addr = engine_page_size * 3;
+	for (i = 2; i < engine_page_size / sizeof(uint32_t); i++) {
+		uint8_t slots, version, type, crc;
+		struct fsi_device *dev;
+
+		rc = fsi_slave_read(slave, (i + 1) * sizeof(conf),
+				&conf, sizeof(conf));
+		if (rc) {
+			dev_warn(&slave->dev,
+				"error reading slave registers\n");
+			return -1;
+		}
+		conf = be32_to_cpu(conf);
+
+		crc = fsi_crc4(0, conf, 32);
+		if (crc) {
+			dev_warn(&slave->dev,
+				"crc error in slave register at 0x%04x\n",
+				i);
+			return -1;
+		}
+
+		slots = (conf & FSI_SLAVE_CONF_SLOTS_MASK)
+			>> FSI_SLAVE_CONF_SLOTS_SHIFT;
+		version = (conf & FSI_SLAVE_CONF_VERSION_MASK)
+			>> FSI_SLAVE_CONF_VERSION_SHIFT;
+		type = (conf & FSI_SLAVE_CONF_TYPE_MASK)
+			>> FSI_SLAVE_CONF_TYPE_SHIFT;
+
+		/*
+		 * Unused address areas are marked by a zero type value; this
+		 * skips the defined address areas
+		 */
+		if (type != 0 && slots != 0) {
+
+			/* create device */
+			dev = fsi_create_device(slave);
+			if (!dev)
+				return -ENOMEM;
+
+			dev->slave = slave;
+			dev->engine_type = type;
+			dev->version = version;
+			dev->unit = i;
+			dev->addr = engine_addr;
+			dev->size = slots * engine_page_size;
+
+			dev_info(&slave->dev,
+			"engine[%i]: type %x, version %x, addr %x size %x\n",
+					dev->unit, dev->engine_type, version,
+					dev->addr, dev->size);
+
+			dev_set_name(&dev->dev, "%02x:%02x:%02x:%02x",
+					slave->master->idx, slave->link,
+					slave->id, i - 2);
+
+			rc = device_register(&dev->dev);
+			if (rc) {
+				dev_warn(&slave->dev, "add failed: %d\n", rc);
+				put_device(&dev->dev);
+			}
+		}
+
+		engine_addr += slots * engine_page_size;
+
+		if (!(conf & FSI_SLAVE_CONF_NEXT_MASK))
+			break;
+	}
+
+	return 0;
+}
+
 /* Encode slave local bus echo delay */
 static inline uint32_t fsi_smode_echodly(int x)
 {
@@ -253,9 +375,8 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 		return rc;
 	}
 
-	/* todo: perform engine scan */
-
-	return rc;
+	fsi_slave_scan(slave);
+	return 0;
 }
 
 /* FSI master support */
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index 273cbf6..efa55ba 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -21,6 +21,10 @@ struct fsi_device {
 	struct device		dev;
 	u8			engine_type;
 	u8			version;
+	u8			unit;
+	struct fsi_slave	*slave;
+	uint32_t		addr;
+	uint32_t		size;
 };
 
 struct fsi_device_id {
-- 
1.8.2.2

^ permalink raw reply related

* [PATCH v6 08/23] drivers/fsi: Set slave SMODE to init communication
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, rostedt, mingo, gregkh, devicetree,
	linux-arm-kernel
  Cc: Chris Bostic, joel, linux-kernel, andrew, alistair, benh,
	Jeremy Kerr
In-Reply-To: <20170410194706.64280-1-cbostic@linux.vnet.ibm.com>

From: Chris Bostic <cbostic@linux.vnet.ibm.com>

Set CFAM to appropriate ID so that the controlling master can manage
link memory ranges.  Add slave engine register definitions.

Includes changes from Jeremy Kerr <jk@ozlabs.org>.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@linux.vnet.ibm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 drivers/fsi/fsi-core.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index c705ca2..b7b138b 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -21,6 +21,27 @@
 
 #include "fsi-master.h"
 
+#define FSI_SLAVE_BASE			0x800
+
+/*
+ * FSI slave engine control register offsets
+ */
+#define FSI_SMODE			0x0	/* R/W: Mode register */
+
+/*
+ * SMODE fields
+ */
+#define FSI_SMODE_WSC		0x80000000	/* Warm start done */
+#define FSI_SMODE_ECRC		0x20000000	/* Hw CRC check */
+#define FSI_SMODE_SID_SHIFT	24		/* ID shift */
+#define FSI_SMODE_SID_MASK	3		/* ID Mask */
+#define FSI_SMODE_ED_SHIFT	20		/* Echo delay shift */
+#define FSI_SMODE_ED_MASK	0xf		/* Echo delay mask */
+#define FSI_SMODE_SD_SHIFT	16		/* Send delay shift */
+#define FSI_SMODE_SD_MASK	0xf		/* Send delay mask */
+#define FSI_SMODE_LBCRR_SHIFT	8		/* Clk ratio shift */
+#define FSI_SMODE_LBCRR_MASK	0xf		/* Clk ratio mask */
+
 #define FSI_SLAVE_SIZE_23b		0x800000
 
 static DEFINE_IDA(master_ida);
@@ -117,6 +138,52 @@ static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 			addr, val, size);
 }
 
+/* Encode slave local bus echo delay */
+static inline uint32_t fsi_smode_echodly(int x)
+{
+	return (x & FSI_SMODE_ED_MASK) << FSI_SMODE_ED_SHIFT;
+}
+
+/* Encode slave local bus send delay */
+static inline uint32_t fsi_smode_senddly(int x)
+{
+	return (x & FSI_SMODE_SD_MASK) << FSI_SMODE_SD_SHIFT;
+}
+
+/* Encode slave local bus clock rate ratio */
+static inline uint32_t fsi_smode_lbcrr(int x)
+{
+	return (x & FSI_SMODE_LBCRR_MASK) << FSI_SMODE_LBCRR_SHIFT;
+}
+
+/* Encode slave ID */
+static inline uint32_t fsi_smode_sid(int x)
+{
+	return (x & FSI_SMODE_SID_MASK) << FSI_SMODE_SID_SHIFT;
+}
+
+static const uint32_t fsi_slave_smode(int id)
+{
+	return FSI_SMODE_WSC | FSI_SMODE_ECRC
+		| fsi_smode_sid(id)
+		| fsi_smode_echodly(0xf) | fsi_smode_senddly(0xf)
+		| fsi_smode_lbcrr(0x8);
+}
+
+static int fsi_slave_set_smode(struct fsi_master *master, int link, int id)
+{
+	uint32_t smode;
+
+	/* set our smode register with the slave ID field to 0; this enables
+	 * extended slave addressing
+	 */
+	smode = fsi_slave_smode(id);
+	smode = cpu_to_be32(smode);
+
+	return fsi_master_write(master, link, id, FSI_SLAVE_BASE + FSI_SMODE,
+			&smode, sizeof(smode));
+}
+
 static void fsi_slave_release(struct device *dev)
 {
 	struct fsi_slave *slave = to_fsi_slave(dev);
@@ -155,6 +222,14 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 	dev_info(&master->dev, "fsi: found chip %08x at %02x:%02x:%02x\n",
 			chip_id, master->idx, link, id);
 
+	rc = fsi_slave_set_smode(master, link, id);
+	if (rc) {
+		dev_warn(&master->dev,
+				"can't set smode on slave:%02x:%02x %d\n",
+				link, id, rc);
+		return -ENODEV;
+	}
+
 	/* We can communicate with a slave; create the slave device and
 	 * register.
 	 */
-- 
1.8.2.2

^ permalink raw reply related

* [PATCH v6 07/23] drivers/fsi: Implement slave initialisation
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, rostedt, mingo, gregkh, devicetree,
	linux-arm-kernel
  Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
	Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic@linux.vnet.ibm.com>

From: Jeremy Kerr <jk@ozlabs.org>

Implement fsi_slave_init: if we can read a chip ID, create fsi_slave
devices and register with the driver core.

Includes changes from Chris Bostic <cbostic@linux.vnet.ibm.com>.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@linux.vnet.ibm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 drivers/fsi/fsi-core.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 6e1cfdf..c705ca2 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -17,9 +17,12 @@
 #include <linux/fsi.h>
 #include <linux/idr.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 
 #include "fsi-master.h"
 
+#define FSI_SLAVE_SIZE_23b		0x800000
+
 static DEFINE_IDA(master_ida);
 
 struct fsi_slave {
@@ -114,11 +117,70 @@ static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 			addr, val, size);
 }
 
+static void fsi_slave_release(struct device *dev)
+{
+	struct fsi_slave *slave = to_fsi_slave(dev);
+
+	kfree(slave);
+}
+
 static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 {
-	/* todo: initialise slave device, perform engine scan */
+	struct fsi_slave *slave;
+	uint32_t chip_id;
+	uint8_t crc;
+	int rc;
+
+	/* Currently, we only support single slaves on a link, and use the
+	 * full 23-bit address range
+	 */
+	if (id != 0)
+		return -EINVAL;
+
+	rc = fsi_master_read(master, link, id, 0, &chip_id, sizeof(chip_id));
+	if (rc) {
+		dev_warn(&master->dev, "can't read slave %02x:%02x %d\n",
+				link, id, rc);
+		return -ENODEV;
+	}
+	chip_id = be32_to_cpu(chip_id);
+
+	crc = fsi_crc4(0, chip_id, 32);
+	if (crc) {
+		dev_warn(&master->dev, "slave %02x:%02x invalid chip id CRC!\n",
+				link, id);
+		return -EIO;
+	}
+
+	dev_info(&master->dev, "fsi: found chip %08x at %02x:%02x:%02x\n",
+			chip_id, master->idx, link, id);
+
+	/* We can communicate with a slave; create the slave device and
+	 * register.
+	 */
+	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
+	if (!slave)
+		return -ENOMEM;
+
+	slave->master = master;
+	slave->dev.parent = &master->dev;
+	slave->dev.release = fsi_slave_release;
+	slave->link = link;
+	slave->id = id;
+	slave->size = FSI_SLAVE_SIZE_23b;
+
+	dev_set_name(&slave->dev, "slave@%02x:%02x", link, id);
+	rc = device_register(&slave->dev);
+	if (rc < 0) {
+		dev_warn(&master->dev, "failed to create slave device: %d\n",
+				rc);
+		put_device(&slave->dev);
+		return rc;
+	}
+
+	/* todo: perform engine scan */
 
-	return -ENODEV;
+	return rc;
 }
 
 /* FSI master support */
-- 
1.8.2.2

^ permalink raw reply related

* [PATCH v6 06/23] drivers/fsi: Set up links for slave communication
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	mingo-H+wXaHxf7aLQT0dZR+AlfA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Chris Bostic, joel-U3u1mxZcP9KHXe+LvDLADg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
	alistair-Y4h6yKqj69EXC2x5gXVKYQ,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r
In-Reply-To: <20170410194706.64280-1-cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

From: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

Enable each link and send a break command, and try to detect a slave by
reading from the SMODE register.

Signed-off-by: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Signed-off-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
---
 drivers/fsi/fsi-core.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 32698ed..6e1cfdf 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -157,12 +157,45 @@ static int fsi_master_write(struct fsi_master *master, int link,
 	return master->write(master, link, slave_id, addr, val, size);
 }
 
+static int fsi_master_link_enable(struct fsi_master *master, int link)
+{
+	if (master->link_enable)
+		return master->link_enable(master, link);
+
+	return 0;
+}
+
+/*
+ * Issue a break command on this link
+ */
+static int fsi_master_break(struct fsi_master *master, int link)
+{
+	if (master->send_break)
+		return master->send_break(master, link);
+
+	return 0;
+}
+
 static int fsi_master_scan(struct fsi_master *master)
 {
-	int link;
+	int link, rc;
+
+	for (link = 0; link < master->n_links; link++) {
+		rc = fsi_master_link_enable(master, link);
+		if (rc) {
+			dev_dbg(&master->dev,
+				"enable link %d failed: %d\n", link, rc);
+			continue;
+		}
+		rc = fsi_master_break(master, link);
+		if (rc) {
+			dev_dbg(&master->dev,
+				"break to link %d failed: %d\n", link, rc);
+			continue;
+		}
 
-	for (link = 0; link < master->n_links; link++)
 		fsi_slave_init(master, link, 0);
+	}
 
 	return 0;
 }
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v6 05/23] drivers/fsi: Add slave & master read/write APIs
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	mingo-H+wXaHxf7aLQT0dZR+AlfA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
	alistair-Y4h6yKqj69EXC2x5gXVKYQ,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>

Introduce functions to perform reads/writes on the slave address space;
these simply pass the request on the slave's master with the correct
link and slave ID.

We implement these on top of similar helpers for the master.

Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
 drivers/fsi/fsi-core.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 4bbca95..32698ed 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -32,6 +32,11 @@ struct fsi_slave {
 
 #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
 
+static int fsi_master_read(struct fsi_master *master, int link,
+		uint8_t slave_id, uint32_t addr, void *val, size_t size);
+static int fsi_master_write(struct fsi_master *master, int link,
+		uint8_t slave_id, uint32_t addr, const void *val, size_t size);
+
 /* crc helpers */
 static const uint8_t crc4_tab[] = {
 	0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
@@ -57,6 +62,58 @@ uint8_t fsi_crc4(uint8_t c, uint64_t x, int bits)
 EXPORT_SYMBOL_GPL(fsi_crc4);
 
 /* FSI slave support */
+static int fsi_slave_calc_addr(struct fsi_slave *slave, uint32_t *addrp,
+		uint8_t *idp)
+{
+	uint32_t addr = *addrp;
+	uint8_t id = *idp;
+
+	if (addr > slave->size)
+		return -EINVAL;
+
+	/* For 23 bit addressing, we encode the extra two bits in the slave
+	 * id (and the slave's actual ID needs to be 0).
+	 */
+	if (addr > 0x1fffff) {
+		if (slave->id != 0)
+			return -EINVAL;
+		id = (addr >> 21) & 0x3;
+		addr &= 0x1fffff;
+	}
+
+	*addrp = addr;
+	*idp = id;
+	return 0;
+}
+
+static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
+			void *val, size_t size)
+{
+	uint8_t id = slave->id;
+	int rc;
+
+	rc = fsi_slave_calc_addr(slave, &addr, &id);
+	if (rc)
+		return rc;
+
+	return fsi_master_read(slave->master, slave->link, id,
+			addr, val, size);
+}
+
+static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
+			const void *val, size_t size)
+{
+	uint8_t id = slave->id;
+	int rc;
+
+	rc = fsi_slave_calc_addr(slave, &addr, &id);
+	if (rc)
+		return rc;
+
+	return fsi_master_write(slave->master, slave->link, id,
+			addr, val, size);
+}
+
 static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 {
 	/* todo: initialise slave device, perform engine scan */
@@ -65,6 +122,41 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 }
 
 /* FSI master support */
+static int fsi_check_access(uint32_t addr, size_t size)
+{
+	if (size != 1 && size != 2 && size != 4)
+		return -EINVAL;
+
+	if ((addr & 0x3) != (size & 0x3))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int fsi_master_read(struct fsi_master *master, int link,
+		uint8_t slave_id, uint32_t addr, void *val, size_t size)
+{
+	int rc;
+
+	rc = fsi_check_access(addr, size);
+	if (rc)
+		return rc;
+
+	return master->read(master, link, slave_id, addr, val, size);
+}
+
+static int fsi_master_write(struct fsi_master *master, int link,
+		uint8_t slave_id, uint32_t addr, const void *val, size_t size)
+{
+	int rc;
+
+	rc = fsi_check_access(addr, size);
+	if (rc)
+		return rc;
+
+	return master->write(master, link, slave_id, addr, val, size);
+}
+
 static int fsi_master_scan(struct fsi_master *master)
 {
 	int link;
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v6 04/23] drivers/fsi: Add crc4 helpers
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, rostedt, mingo, gregkh, devicetree,
	linux-arm-kernel
  Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
	Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic@linux.vnet.ibm.com>

From: Jeremy Kerr <jk@ozlabs.org>

Add some helpers for the crc checks for the slave configuration table.
This works 4-bits-at-a-time, using a simple table approach.

We will need this in the FSI core code, as well as any master
implementations that need to calculate CRCs in software.

We add this to the fsi code (rather than lib/), as we need a specific
polynomial for FSI CRCs.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@linux.vnet.ibm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 drivers/fsi/fsi-core.c   | 24 ++++++++++++++++++++++++
 drivers/fsi/fsi-master.h | 21 +++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index e90d45d..4bbca95 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -32,6 +32,30 @@ struct fsi_slave {
 
 #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
 
+/* crc helpers */
+static const uint8_t crc4_tab[] = {
+	0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
+	0x1, 0x6, 0xf, 0x8, 0xa, 0xd, 0x4, 0x3,
+};
+
+uint8_t fsi_crc4(uint8_t c, uint64_t x, int bits)
+{
+	int i;
+
+	/* Align to 4-bits */
+	bits = (bits + 3) & ~0x3;
+
+	/* mask off anything above the top bit */
+	x &= (1ull << bits) - 1;
+
+	/* Calculate crc4 over four-bit nibbles, starting at the MSbit */
+	for (i = bits - 4; i >= 0; i -= 4)
+		c = crc4_tab[c ^ ((x >> i) & 0xf)];
+
+	return c;
+}
+EXPORT_SYMBOL_GPL(fsi_crc4);
+
 /* FSI slave support */
 static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 {
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index 7764b00..d6a4885 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -38,4 +38,25 @@ struct fsi_master {
 extern int fsi_master_register(struct fsi_master *master);
 extern void fsi_master_unregister(struct fsi_master *master);
 
+/**
+ * crc4 helper: Given a starting crc4 state @c, calculate the crc4 vaue of @x,
+ * which is @bits in length. This may be required by master implementations
+ * that do not provide their own hardware checksums.
+ *
+ * The crc4 is performed on 4-bit chunks (which is all we need for FSI
+ * calculations). Typically, we'll want a starting state of 0:
+ *
+ *  c = fsi_crc4(0, msg, len);
+ *
+ * To crc4 a message that includes a single start bit, initialise crc4 state
+ * with:
+ *
+ *  c = fsi_crc4(0, 1, 1);
+ *
+ * Then update with message data:
+ *
+ *  c = fsi_crc4(c, msg, len);
+ */
+uint8_t fsi_crc4(uint8_t c, uint64_t x, int bits);
+
 #endif /* DRIVERS_FSI_MASTER_H */
-- 
1.8.2.2

^ permalink raw reply related

* [PATCH v6 03/23] drivers/fsi: Add empty master scan
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, rostedt, mingo, gregkh, devicetree,
	linux-arm-kernel
  Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
	Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic@linux.vnet.ibm.com>

From: Jeremy Kerr <jk@ozlabs.org>

When a new fsi master is added, we will need to scan its links, and
slaves attached to those links. This change introduces a little shell to
iterate the links, which we will populate with the actual slave scan in
a later change.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@linux.vnet.ibm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 drivers/fsi/fsi-core.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 2f19509..e90d45d 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -32,7 +32,25 @@ struct fsi_slave {
 
 #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
 
+/* FSI slave support */
+static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
+{
+	/* todo: initialise slave device, perform engine scan */
+
+	return -ENODEV;
+}
+
 /* FSI master support */
+static int fsi_master_scan(struct fsi_master *master)
+{
+	int link;
+
+	for (link = 0; link < master->n_links; link++)
+		fsi_slave_init(master, link, 0);
+
+	return 0;
+}
+
 int fsi_master_register(struct fsi_master *master)
 {
 	int rc;
@@ -44,10 +62,13 @@ int fsi_master_register(struct fsi_master *master)
 	dev_set_name(&master->dev, "fsi%d", master->idx);
 
 	rc = device_register(&master->dev);
-	if (rc)
+	if (rc) {
 		ida_simple_remove(&master_ida, master->idx);
+		return rc;
+	}
 
-	return rc;
+	fsi_master_scan(master);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(fsi_master_register);
 
-- 
1.8.2.2

^ permalink raw reply related

* [PATCH v6 02/23] drivers/fsi: Add slave definition
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, rostedt, mingo, gregkh, devicetree,
	linux-arm-kernel
  Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
	Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic@linux.vnet.ibm.com>

From: Jeremy Kerr <jk@ozlabs.org>

Add the initial fsi slave device, which is private to the core code.
This will be a child of the master, and parent to endpoint devices.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@linux.vnet.ibm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 drivers/fsi/fsi-core.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index ca02913..2f19509 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -22,6 +22,16 @@
 
 static DEFINE_IDA(master_ida);
 
+struct fsi_slave {
+	struct device		dev;
+	struct fsi_master	*master;
+	int			id;
+	int			link;
+	uint32_t		size;	/* size of slave address space */
+};
+
+#define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
+
 /* FSI master support */
 int fsi_master_register(struct fsi_master *master)
 {
-- 
1.8.2.2

^ permalink raw reply related

* [PATCH v6 01/23] drivers/fsi: Add fsi master definition
From: Christopher Bostic @ 2017-04-10 19:46 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, rostedt-nx8X9YLhiw1AfugRpC6u6w,
	mingo-H+wXaHxf7aLQT0dZR+AlfA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
	alistair-Y4h6yKqj69EXC2x5gXVKYQ,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Chris Bostic
In-Reply-To: <20170410194706.64280-1-cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>

Add a `struct fsi_master` to represent a FSI master controller.

FSI master drivers register one of these structs to provide
device-specific of the standard operations: read/write/term/break and
link control.

Includes changes from Edward A. James <eajames-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org> & Jeremy Kerr
<jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>.

Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Signed-off-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
---
 drivers/fsi/fsi-core.c   | 35 +++++++++++++++++++++++++++++++++++
 drivers/fsi/fsi-master.h | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)
 create mode 100644 drivers/fsi/fsi-master.h

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 3d55bd5..ca02913 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -15,8 +15,43 @@
 
 #include <linux/device.h>
 #include <linux/fsi.h>
+#include <linux/idr.h>
 #include <linux/module.h>
 
+#include "fsi-master.h"
+
+static DEFINE_IDA(master_ida);
+
+/* FSI master support */
+int fsi_master_register(struct fsi_master *master)
+{
+	int rc;
+
+	if (!master)
+		return -EINVAL;
+
+	master->idx = ida_simple_get(&master_ida, 0, INT_MAX, GFP_KERNEL);
+	dev_set_name(&master->dev, "fsi%d", master->idx);
+
+	rc = device_register(&master->dev);
+	if (rc)
+		ida_simple_remove(&master_ida, master->idx);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(fsi_master_register);
+
+void fsi_master_unregister(struct fsi_master *master)
+{
+	if (master->idx >= 0) {
+		ida_simple_remove(&master_ida, master->idx);
+		master->idx = -1;
+	}
+
+	device_unregister(&master->dev);
+}
+EXPORT_SYMBOL_GPL(fsi_master_unregister);
+
 /* FSI core & Linux bus type definitions */
 
 static int fsi_bus_match(struct device *dev, struct device_driver *drv)
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
new file mode 100644
index 0000000..7764b00
--- /dev/null
+++ b/drivers/fsi/fsi-master.h
@@ -0,0 +1,41 @@
+/*
+ * FSI master definitions. These comprise the core <--> master interface,
+ * to allow the core to interact with the (hardware-specific) masters.
+ *
+ * Copyright (C) IBM Corporation 2016
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef DRIVERS_FSI_MASTER_H
+#define DRIVERS_FSI_MASTER_H
+
+#include <linux/device.h>
+
+struct fsi_master {
+	struct device	dev;
+	int		idx;
+	int		n_links;
+	int		flags;
+	int		(*read)(struct fsi_master *, int link, uint8_t id,
+				uint32_t addr, void *val, size_t size);
+	int		(*write)(struct fsi_master *, int link, uint8_t id,
+				uint32_t addr, const void *val, size_t size);
+	int		(*term)(struct fsi_master *, int link, uint8_t id);
+	int		(*send_break)(struct fsi_master *, int link);
+	int		(*link_enable)(struct fsi_master *, int link);
+};
+
+#define dev_to_fsi_master(d) container_of(d, struct fsi_master, dev)
+
+extern int fsi_master_register(struct fsi_master *master);
+extern void fsi_master_unregister(struct fsi_master *master);
+
+#endif /* DRIVERS_FSI_MASTER_H */
-- 
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [alsa-devel] [PATCH v4 6/9] ASoC: add snd_soc_get_dai_id()
From: Rob Herring @ 2017-04-10 19:43 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-DT, Linux-ALSA, Mark Brown, Simon
In-Reply-To: <8737dh5c26.wl%kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>

On Sun, Apr 9, 2017 at 7:45 PM, Kuninori Morimoto
<kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org> wrote:
>
> Hi Rob, again
>
>> > >> > +{
>> > >> > +       struct device_node *node;
>> > >> > +       struct device_node *endpoint;
>> > >> > +       int i, id;
>> > >> > +
>> > >> > +       node = of_graph_get_port_parent(ep);
>> > >> > +
>> > >> > +       i = 0;
>> > >> > +       id = -1;
>> > >> > +       for_each_endpoint_of_node(node, endpoint) {
>> > >> > +               if (endpoint == ep)
>> > >> > +                       id = i;
>> > >>
>> > >> I don't see how this works when you have 1 DAI controller with
>> > >> multiple endpoints versus multiple DAI controllers with a single
>> > >> endpoint each. All the IDs will be 0 in the latter case.
>> > >
>> > > It support 1:1 endpoint pattern only.
>> >
>> > Then the endpoint id is always 0 and this function is pointless.
>>
>> Sorry, I checked my patch-list, and I noticed that
>> this function will be expand to use callback function in next
>> patch-set (= HDMI support).
>> Thus, inded current function is pointless at this point.
>> I will merge this expansion patch in v5
>
> 1 correction.
>
> sound graph might have multi ports (= not multi endpoint), like below.
> Each endpoints are 1:1.
>
> ports {
>         port { endpoint }; /* ID = 0 */

port@0

>         port { endpoint }; /* ID = 1 */

port@1, etc.

>         port { endpoint }; /* ID = 2 */

These ports are audio channels? If these are 3 separate data paths,
then this is correct. If you have a single data path with multiple
connections (e.g. a mux), then that should be a single port with
multiple endpoints. For example, a design that routes the same I2S
interface to HDMI and a codec and their use is mutually exclusive. I
imagine you will need to support both.

The pattern I prefer to see calling graph functions is that drivers
are specific about which port and endpoint number for a parent node
they want. Not just searching the graph for any match.

> };
>
> 1 question
>
> It will support HDMI sound feature, thus I separated
> it into OF-graph (= this patch-set) and HDMI (= next patch-set).
> Should I merge it ?

I think so if it affects the functions here. It seems better to let
the driver controlling the DAI determine the id mapping than trying to
do it in the core.

> Below is the expansion patch for HDMI support
>
> ----------------------
> Subject: [PATCH 14/63] ASoC: add .of_xlate_dai_id() callback
>
> ALSA SoC needs to know connected DAI ID for probing.
> It is not a big problem if device/driver was only for sound,
> but getting DAI ID will be difficult if device includes both
> Video/Sound, like HDMI.
> To solve this issue, this patch adds new .of_xlate_dai_id callback
> on component driver, and use it from snd_soc_get_dai_id()
>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
> ---
>  include/sound/soc.h  |  3 +++
>  sound/soc/soc-core.c | 33 +++++++++++++++++++++++++++++++++
>  2 files changed, 36 insertions(+)
>
> diff --git a/include/sound/soc.h b/include/sound/soc.h
> index 95abbcb..0055fa0 100644
> --- a/include/sound/soc.h
> +++ b/include/sound/soc.h
> @@ -14,6 +14,7 @@
>  #define __LINUX_SND_SOC_H
>
>  #include <linux/of.h>
> +#include <linux/of_graph.h>
>  #include <linux/platform_device.h>
>  #include <linux/types.h>
>  #include <linux/notifier.h>
> @@ -793,6 +794,8 @@ struct snd_soc_component_driver {
>         int (*of_xlate_dai_name)(struct snd_soc_component *component,
>                                  struct of_phandle_args *args,
>                                  const char **dai_name);
> +       int (*of_xlate_dai_id)(struct snd_soc_component *comment,
> +                              struct device_node *endpoint);
>         void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
>                 int subseq);
>         int (*stream_event)(struct snd_soc_component *, int event);
> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
> index 7a10522..07e4eec 100644
> --- a/sound/soc/soc-core.c
> +++ b/sound/soc/soc-core.c
> @@ -4042,12 +4042,45 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
>
>  int snd_soc_get_dai_id(struct device_node *ep)
>  {
> +       struct snd_soc_component *pos;
>         struct device_node *node;
>         struct device_node *endpoint;
>         int i, id;
> +       int ret;
>
>         node = of_graph_get_port_parent(ep);
>
> +       /*
> +        * For example HDMI case, HDMI has video/sound port,
> +        * but ALSA SoC needs sound port number only.
> +        * Thus counting HDMI DT port/endpoint doesn't work.
> +        * Then, it should have .of_xlate_dai_id

Perhaps you should always require this function and provide a default
implementation (or several).

> +        */
> +       ret = -ENOTSUPP;
> +       mutex_lock(&client_mutex);
> +       list_for_each_entry(pos, &component_list, list) {
> +               struct device_node *component_of_node = pos->dev->of_node;
> +
> +               if (!component_of_node && pos->dev->parent)
> +                       component_of_node = pos->dev->parent->of_node;
> +
> +               if (component_of_node != node)
> +                       continue;
> +
> +               if (pos->driver->of_xlate_dai_id)
> +                       ret = pos->driver->of_xlate_dai_id(pos, ep);
> +
> +               break;
> +       }
> +       mutex_unlock(&client_mutex);
> +
> +       if (ret != -ENOTSUPP)
> +               return ret;
> +
> +       /*
> +        * Non HDMI sound case, counting port/endpoint on its DT
> +        * is enough. Let's count it.
> +        */
>         i = 0;
>         id = -1;
>         for_each_endpoint_of_node(node, endpoint) {
> --
> 1.9.1
>
> ----------------------
>
> Best regards
> ---
> Kuninori Morimoto
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 3/6] dt-bindings: correct marvell orion MDIO binding document
From: Andrew Lunn @ 2017-04-10 19:28 UTC (permalink / raw)
  To: Russell King
  Cc: Marcin Wojtas, Stefan Chulski, Thomas Petazzoni, Rob Herring,
	Mark Rutland, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <E1cxbEl-0006gK-1Q-eh5Bv4kxaXIk46pC+1QYvQNdhmdF6hFW@public.gmane.org>

On Mon, Apr 10, 2017 at 04:28:15PM +0100, Russell King wrote:
> Correct the Marvell Orion MDIO binding document to properly reflect the
> cases where an interrupt is present.  Augment the examples to show this.
> 
> Signed-off-by: Russell King <rmk+kernel-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org>

Reviewed-by: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>

    Andrew
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/2] leds: Add driver for Qualcomm LPG
From: Bjorn Andersson @ 2017-04-10 19:19 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Jacek Anaszewski, Rob Herring, Richard Purdie, linux-kernel,
	linux-leds, linux-arm-msm, Mark Rutland, devicetree
In-Reply-To: <20170408133904.GA9020@amd>

On Sat 08 Apr 06:39 PDT 2017, Pavel Machek wrote:

> Hi!
> 
> > [..]
> > > > For the patterns I don't know how a trigger for this would look like,
> > > > how would setting the pattern of a trigger be propagated down to the
> > > > hardware?
> > > 
> > > We'd need a new op and API similar to blink_set()/led_blink_set().
> > > 
> > 
> > I've tried to find different LED circuits with some sort of pattern
> > generator in an attempt to figure out how to design this interface, but
> > turned out to be quite hard to find examples; the three I can compare
> > are:
> > 
> > * LP5xx series "implements" pattern generation by executing code.
> > 
> > * Qualcomm LPG iterates over 2-64 brightness-values in a pattern, at a
> >   fixed rate with knobs to configure what happens before starting and
> >   after finishing iterating over the defined values. It does not support
> >   smooth transitions between values.
> > 
> > * AS3676 supports a pattern of 32 values controlling if the output
> >   should be enabled or disabled for each 32.5ms (or 250ms) time period.
> >   The delay before repeating the pattern can be configured. It support
> >   smooth transitions between the states.
> > 
> > 
> > So, while I think I see how you would like to architect this interface I
> > am not sure how to figure out the details.
> > 
> > The pattern definition would have to be expressive enough to support the
> > features of LP5xx and direct enough to support the limited AS3676. It
> > would likely have to express transitions, so that the LPG could generate
> > intermediate steps (and we will have to adapt the resolution of the
> > ramps based on the other LPGs in the system).
> > 
> > How do we do with patterns that are implementable by the LP5xx but are
> > not with the LPG? Should we reject those or should we do some sort of
> > best-effort approach in the kernel?
> 
> Lets say you get series of
> 
> (red, green, blue, delta_t )
> 
> points, meaning "in delta_t msec, change color to red, green,
> blue. Lets ignore other channels for now. delta_t of 0 would be step
> change. Would such interface work for you?
> 

So I presume this would be input to the RGB trigger that we discussed.
But in my current device I have 6 LEDs, that are not in any RGB-like
configuration. So we would need to come up with an interface that looks
to be the same in both single-LED and RGB-LED setups.


This should be sufficient to describe a subset of the patterns I've seen
so far in products.

But let's consider the standard use case for an RGB LED on an Android
phone; continuously blinking (pulsing based on patterns) as you have
some notifications waiting. In this case you want the LED hardware to do
all the work, so that you can deep-idle the CPU. So we would need to
introduce a "repeat pattern"-command.

Then consider the fact that you want your patterns to have decent
resolution, but you have a limited amount of storage. So we either have
to be able to detect palindromes or have a way to represent this.

> Simple compiler from this to LP5XX code should not be hard to
> do.

It sounds fairly straight forward to convert a pattern to instructions,
but we do have an extremely limited amount of storage so it must be a
quite good implementation for people to be able to use it for anything
real.

We could implement some optimization steps where we try to detect slopes
and generate ramp-instructions instead of set-pwm + wait instructions,
use some variables to handle ramp up/down and we could probably generate
some jump instructions to implement loops.

But do we really want this logic in the kernel, for each LED chip
supporting patterns?

> AS3676 ... I'm not sure what to do, AFAICT it is too limited.
> 

So out of the three examples I've looked at we're skipping one and we're
abstracting away most functionality from another.

I'm sorry for being pessimistic about this, but while I can see the
theoretical benefit of providing a uniform interface for this to user
space I see three very different pieces of hardware that would be used
in three different ways in products.

Regards,
Bjorn

^ permalink raw reply

* Re: [PATCH v4 3/9] dt-bindings: pinctrl: Add RZ/A1 bindings doc
From: jmondi @ 2017-04-10 19:19 UTC (permalink / raw)
  To: Rob Herring
  Cc: Jacopo Mondi, linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
	geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
	laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
	chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ, mark.rutland-5wv7dgnIgG8,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
	linux-gpio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170410181215.e6cihbv2rfljbm3b@rob-hp-laptop>

Hi Rob,

On Mon, Apr 10, 2017 at 01:12:15PM -0500, Rob Herring wrote:
> On Wed, Apr 05, 2017 at 04:07:21PM +0200, Jacopo Mondi wrote:
> > Add device tree bindings documentation for Renesas RZ/A1 gpio and pin
> > controller.
> >
> > Signed-off-by: Jacopo Mondi <jacopo+renesas-AW8dsiIh9cEdnm+yROfE0A@public.gmane.org>
> > ---
> >  .../bindings/pinctrl/renesas,rza1-pinctrl.txt      | 218 +++++++++++++++++++++
> >  1 file changed, 218 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
> >
> > diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
> > new file mode 100644
> > index 0000000..46584ef
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
> > @@ -0,0 +1,218 @@
> > +Renesas RZ/A1 combined Pin and GPIO controller
> > +
> > +The Renesas SoCs of RZ/A1 family feature a combined Pin and GPIO controller,
> > +named "Ports" in the hardware reference manual.
> > +Pin multiplexing and GPIO configuration is performed on a per-pin basis
> > +writing configuration values to per-port register sets.
> > +Each "port" features up to 16 pins, each of them configurable for GPIO
> > +function (port mode) or in alternate function mode.
> > +Up to 8 different alternate function modes exist for each single pin.
> > +
> > +Pin controller node
> > +-------------------
> > +
> > +Required properties:
> > +  - compatible
> > +    this shall be "renesas,r7s72100-ports".
> > +
> > +  - reg
> > +    address base and length of the memory area where pin controller
> > +    hardware is mapped to.
> > +
> > +Example:
> > +Pin controller node for RZ/A1H SoC (r7s72100)
> > +
> > +pinctrl: pin-controller@fcfe3000 {
> > +	compatible = "renesas,r7s72100-ports";
> > +
> > +	reg = <0xfcfe3000 0x4230>;
> > +};
> > +
> > +Sub-nodes
> > +---------
> > +
> > +The child nodes of the pin controller node describe a pin multiplexing
> > +function or a gpio controller alternatively.
> > +
> > +- Pin multiplexing sub-nodes:
> > +  A pin multiplexing sub-node describes how to configure a set of
> > +  (or a single) pin in some desired alternate function mode.
> > +  A single sub-node may define several pin configurations.
> > +  Some alternate functions require special pin configuration flags to be
> > +  supplied along with the alternate function configuration number.
> > +  When hardware reference manual specifies a pin function to be either
> > +  "bi-directional" or "software IO driven", use the generic properties from
> > +  <include/linux/pinctrl/pinconf_generic.h> header file to instruct the
> > +  pin controller to perform the desired pin configuration operations.
> > +  Please refer to pinctrl-bindings.txt to get to know more on generic
> > +  pin properties usage.
> > +
> > +  The allowed generic formats for a pin multiplexing sub-node are the
> > +  following ones:
> > +
> > +  node-1 {
> > +      pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
> > +      GENERIC_PINCONFIG;
>
> What's GENERIC_PINCONFIG? I see this in some other binding docs, but not
> used anywhere. If this is a boolean property then get rid of the all
> caps. If this is a define, then don't use complex defines that expand to
> dts source.

GENERIC_PINCONF is a wildcard that identifies "generic" pin
configuration properties the pin controller framework defines.

Have a look at "enum pin_config_param" in
<include/linux/pinctrl/pinconf-generic.h>

Thanks
  j
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Applied "regulator: Add driver for voltage controlled regulators" to the regulator tree
From: Mark Brown @ 2017-04-10 18:43 UTC (permalink / raw)
  To: Matthias Kaehlcke; +Cc: Rob Herring, Mark Brown, Liam Girdwood
In-Reply-To: <20170407195158.63546-1-mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

The patch

   regulator: Add driver for voltage controlled regulators

has been applied to the regulator tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 9dee7a72d0c7cdfa2573c48b1e5f928c721d54d5 Mon Sep 17 00:00:00 2001
From: Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Date: Fri, 7 Apr 2017 12:51:58 -0700
Subject: [PATCH] regulator: Add driver for voltage controlled regulators

The output voltage of a voltage controlled regulator can be controlled
through the voltage of another regulator. The current version of this
driver assumes that the output voltage is a linear function of the control
voltage.

Signed-off-by: Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 .../devicetree/bindings/regulator/vctrl.txt        |  49 ++
 drivers/regulator/Kconfig                          |   7 +
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/vctrl-regulator.c                | 546 +++++++++++++++++++++
 4 files changed, 603 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/vctrl.txt
 create mode 100644 drivers/regulator/vctrl-regulator.c

diff --git a/Documentation/devicetree/bindings/regulator/vctrl.txt b/Documentation/devicetree/bindings/regulator/vctrl.txt
new file mode 100644
index 000000000000..601328d7fdbb
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/vctrl.txt
@@ -0,0 +1,49 @@
+Bindings for Voltage controlled regulators
+==========================================
+
+Required properties:
+--------------------
+- compatible		  : must be "vctrl-regulator".
+- regulator-min-microvolt : smallest voltage consumers may set
+- regulator-max-microvolt : largest voltage consumers may set
+- ctrl-supply		  : The regulator supplying the control voltage.
+- ctrl-voltage-range	  : an array of two integer values describing the range
+			    (min/max) of the control voltage. The values specify
+			    the control voltage needed to generate the corresponding
+			    regulator-min/max-microvolt output voltage.
+
+Optional properties:
+--------------------
+- ovp-threshold-percent	: overvoltage protection (OVP) threshold of the
+			  regulator in percent. Some regulators have an OVP
+			  circuitry which shuts down the regulator when the
+			  actual output voltage deviates beyond a certain
+			  margin from the expected value for a given control
+			  voltage. On larger voltage decreases this can occur
+			  undesiredly since the output voltage does not adjust
+			  inmediately to changes in the control voltage. To
+			  avoid this situation the vctrl driver breaks down
+			  larger voltage decreases into multiple steps, where
+			  each step is within the OVP threshold.
+- min-slew-down-rate	: Describes how slowly the regulator voltage will decay
+			  down in the worst case (lightest expected load).
+			  Specified in uV / us (like main regulator ramp rate).
+			  This value is required when ovp-threshold-percent is
+			  specified.
+
+Example:
+
+	vctrl-reg {
+		compatible = "vctrl-regulator";
+		regulator-name = "vctrl_reg";
+
+		ctrl-supply = <&ctrl_reg>;
+
+		regulator-min-microvolt = <800000>;
+		regulator-max-microvolt = <1500000>;
+
+		ctrl-voltage-range = <200000 500000>;
+
+		min-slew-down-rate = <225>;
+		ovp-threshold-percent = <16>;
+	};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 936f7ccc9736..da83a3abe288 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -843,6 +843,13 @@ config REGULATOR_TWL4030
 	  This driver supports the voltage regulators provided by
 	  this family of companion chips.
 
+config REGULATOR_VCTRL
+	tristate "Voltage controlled regulators"
+	depends on OF
+	help
+	  This driver provides support for voltage regulators whose output
+	  voltage is controlled by the voltage of another regulator.
+
 config REGULATOR_VEXPRESS
 	tristate "Versatile Express regulators"
 	depends on VEXPRESS_CONFIG
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 14294692beb9..e246e148a7f9 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -105,6 +105,7 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o
+obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o
 obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
diff --git a/drivers/regulator/vctrl-regulator.c b/drivers/regulator/vctrl-regulator.c
new file mode 100644
index 000000000000..6baadef0ed74
--- /dev/null
+++ b/drivers/regulator/vctrl-regulator.c
@@ -0,0 +1,546 @@
+/*
+ * Driver for voltage controller regulators
+ *
+ * Copyright (C) 2017 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/sort.h>
+
+struct vctrl_voltage_range {
+	int min_uV;
+	int max_uV;
+};
+
+struct vctrl_voltage_ranges {
+	struct vctrl_voltage_range ctrl;
+	struct vctrl_voltage_range out;
+};
+
+struct vctrl_voltage_table {
+	int ctrl;
+	int out;
+	int ovp_min_sel;
+};
+
+struct vctrl_data {
+	struct regulator_dev *rdev;
+	struct regulator_desc desc;
+	struct regulator *ctrl_reg;
+	bool enabled;
+	unsigned int min_slew_down_rate;
+	unsigned int ovp_threshold;
+	struct vctrl_voltage_ranges vrange;
+	struct vctrl_voltage_table *vtable;
+	unsigned int sel;
+};
+
+static int vctrl_calc_ctrl_voltage(struct vctrl_data *vctrl, int out_uV)
+{
+	struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl;
+	struct vctrl_voltage_range *out = &vctrl->vrange.out;
+
+	return ctrl->min_uV +
+		DIV_ROUND_CLOSEST_ULL((s64)(out_uV - out->min_uV) *
+				      (ctrl->max_uV - ctrl->min_uV),
+				      out->max_uV - out->min_uV);
+}
+
+static int vctrl_calc_output_voltage(struct vctrl_data *vctrl, int ctrl_uV)
+{
+	struct vctrl_voltage_range *ctrl = &vctrl->vrange.ctrl;
+	struct vctrl_voltage_range *out = &vctrl->vrange.out;
+
+	if (ctrl_uV < 0) {
+		pr_err("vctrl: failed to get control voltage\n");
+		return ctrl_uV;
+	}
+
+	if (ctrl_uV < ctrl->min_uV)
+		return out->min_uV;
+
+	if (ctrl_uV > ctrl->max_uV)
+		return out->max_uV;
+
+	return out->min_uV +
+		DIV_ROUND_CLOSEST_ULL((s64)(ctrl_uV - ctrl->min_uV) *
+				      (out->max_uV - out->min_uV),
+				      ctrl->max_uV - ctrl->min_uV);
+}
+
+static int vctrl_get_voltage(struct regulator_dev *rdev)
+{
+	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
+	int ctrl_uV = regulator_get_voltage(vctrl->ctrl_reg);
+
+	return vctrl_calc_output_voltage(vctrl, ctrl_uV);
+}
+
+static int vctrl_set_voltage(struct regulator_dev *rdev,
+			     int req_min_uV, int req_max_uV,
+			     unsigned int *selector)
+{
+	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
+	struct regulator *ctrl_reg = vctrl->ctrl_reg;
+	int orig_ctrl_uV = regulator_get_voltage(ctrl_reg);
+	int uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV);
+	int ret;
+
+	if (req_min_uV >= uV || !vctrl->ovp_threshold)
+		/* voltage rising or no OVP */
+		return regulator_set_voltage(
+			ctrl_reg,
+			vctrl_calc_ctrl_voltage(vctrl, req_min_uV),
+			vctrl_calc_ctrl_voltage(vctrl, req_max_uV));
+
+	while (uV > req_min_uV) {
+		int max_drop_uV = (uV * vctrl->ovp_threshold) / 100;
+		int next_uV;
+		int next_ctrl_uV;
+		int delay;
+
+		/* Make sure no infinite loop even in crazy cases */
+		if (max_drop_uV == 0)
+			max_drop_uV = 1;
+
+		next_uV = max_t(int, req_min_uV, uV - max_drop_uV);
+		next_ctrl_uV = vctrl_calc_ctrl_voltage(vctrl, next_uV);
+
+		ret = regulator_set_voltage(ctrl_reg,
+					    next_ctrl_uV,
+					    next_ctrl_uV);
+		if (ret)
+			goto err;
+
+		delay = DIV_ROUND_UP(uV - next_uV, vctrl->min_slew_down_rate);
+		usleep_range(delay, delay + DIV_ROUND_UP(delay, 10));
+
+		uV = next_uV;
+	}
+
+	return 0;
+
+err:
+	/* Try to go back to original voltage */
+	regulator_set_voltage(ctrl_reg, orig_ctrl_uV, orig_ctrl_uV);
+
+	return ret;
+}
+
+static int vctrl_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
+
+	return vctrl->sel;
+}
+
+static int vctrl_set_voltage_sel(struct regulator_dev *rdev,
+				 unsigned int selector)
+{
+	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
+	struct regulator *ctrl_reg = vctrl->ctrl_reg;
+	unsigned int orig_sel = vctrl->sel;
+	int ret;
+
+	if (selector >= rdev->desc->n_voltages)
+		return -EINVAL;
+
+	if (selector >= vctrl->sel || !vctrl->ovp_threshold) {
+		/* voltage rising or no OVP */
+		ret = regulator_set_voltage(ctrl_reg,
+					    vctrl->vtable[selector].ctrl,
+					    vctrl->vtable[selector].ctrl);
+		if (!ret)
+			vctrl->sel = selector;
+
+		return ret;
+	}
+
+	while (vctrl->sel != selector) {
+		unsigned int next_sel;
+		int delay;
+
+		if (selector >= vctrl->vtable[vctrl->sel].ovp_min_sel)
+			next_sel = selector;
+		else
+			next_sel = vctrl->vtable[vctrl->sel].ovp_min_sel;
+
+		ret = regulator_set_voltage(ctrl_reg,
+					    vctrl->vtable[next_sel].ctrl,
+					    vctrl->vtable[next_sel].ctrl);
+		if (ret) {
+			dev_err(&rdev->dev,
+				"failed to set control voltage to %duV\n",
+				vctrl->vtable[next_sel].ctrl);
+			goto err;
+		}
+		vctrl->sel = next_sel;
+
+		delay = DIV_ROUND_UP(vctrl->vtable[vctrl->sel].out -
+				     vctrl->vtable[next_sel].out,
+				     vctrl->min_slew_down_rate);
+		usleep_range(delay, delay + DIV_ROUND_UP(delay, 10));
+	}
+
+	return 0;
+
+err:
+	if (vctrl->sel != orig_sel) {
+		/* Try to go back to original voltage */
+		if (!regulator_set_voltage(ctrl_reg,
+					   vctrl->vtable[orig_sel].ctrl,
+					   vctrl->vtable[orig_sel].ctrl))
+			vctrl->sel = orig_sel;
+		else
+			dev_warn(&rdev->dev,
+				 "failed to restore original voltage\n");
+	}
+
+	return ret;
+}
+
+static int vctrl_list_voltage(struct regulator_dev *rdev,
+			      unsigned int selector)
+{
+	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
+
+	if (selector >= rdev->desc->n_voltages)
+		return -EINVAL;
+
+	return vctrl->vtable[selector].out;
+}
+
+static int vctrl_parse_dt(struct platform_device *pdev,
+			  struct vctrl_data *vctrl)
+{
+	int ret;
+	struct device_node *np = pdev->dev.of_node;
+	u32 pval;
+	u32 vrange_ctrl[2];
+
+	vctrl->ctrl_reg = devm_regulator_get(&pdev->dev, "ctrl");
+	if (IS_ERR(vctrl->ctrl_reg))
+		return PTR_ERR(vctrl->ctrl_reg);
+
+	ret = of_property_read_u32(np, "ovp-threshold-percent", &pval);
+	if (!ret) {
+		vctrl->ovp_threshold = pval;
+		if (vctrl->ovp_threshold > 100) {
+			dev_err(&pdev->dev,
+				"ovp-threshold-percent (%u) > 100\n",
+				vctrl->ovp_threshold);
+			return -EINVAL;
+		}
+	}
+
+	ret = of_property_read_u32(np, "min-slew-down-rate", &pval);
+	if (!ret) {
+		vctrl->min_slew_down_rate = pval;
+
+		/* We use the value as int and as divider; sanity check */
+		if (vctrl->min_slew_down_rate == 0) {
+			dev_err(&pdev->dev,
+				"min-slew-down-rate must not be 0\n");
+			return -EINVAL;
+		} else if (vctrl->min_slew_down_rate > INT_MAX) {
+			dev_err(&pdev->dev, "min-slew-down-rate (%u) too big\n",
+				vctrl->min_slew_down_rate);
+			return -EINVAL;
+		}
+	}
+
+	if (vctrl->ovp_threshold && !vctrl->min_slew_down_rate) {
+		dev_err(&pdev->dev,
+			"ovp-threshold-percent requires min-slew-down-rate\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(np, "regulator-min-microvolt", &pval);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to read regulator-min-microvolt: %d\n", ret);
+		return ret;
+	}
+	vctrl->vrange.out.min_uV = pval;
+
+	ret = of_property_read_u32(np, "regulator-max-microvolt", &pval);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to read regulator-max-microvolt: %d\n", ret);
+		return ret;
+	}
+	vctrl->vrange.out.max_uV = pval;
+
+	ret = of_property_read_u32_array(np, "ctrl-voltage-range", vrange_ctrl,
+					 2);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to read ctrl-voltage-range: %d\n",
+			ret);
+		return ret;
+	}
+
+	if (vrange_ctrl[0] >= vrange_ctrl[1]) {
+		dev_err(&pdev->dev, "ctrl-voltage-range is invalid: %d-%d\n",
+			vrange_ctrl[0], vrange_ctrl[1]);
+		return -EINVAL;
+	}
+
+	vctrl->vrange.ctrl.min_uV = vrange_ctrl[0];
+	vctrl->vrange.ctrl.max_uV = vrange_ctrl[1];
+
+	return 0;
+}
+
+static int vctrl_cmp_ctrl_uV(const void *a, const void *b)
+{
+	const struct vctrl_voltage_table *at = a;
+	const struct vctrl_voltage_table *bt = b;
+
+	return at->ctrl - bt->ctrl;
+}
+
+static int vctrl_init_vtable(struct platform_device *pdev)
+{
+	struct vctrl_data *vctrl = platform_get_drvdata(pdev);
+	struct regulator_desc *rdesc = &vctrl->desc;
+	struct regulator *ctrl_reg = vctrl->ctrl_reg;
+	struct vctrl_voltage_range *vrange_ctrl = &vctrl->vrange.ctrl;
+	int n_voltages;
+	int ctrl_uV;
+	int i, idx_vt;
+
+	n_voltages = regulator_count_voltages(ctrl_reg);
+
+	rdesc->n_voltages = n_voltages;
+
+	/* determine number of steps within the range of the vctrl regulator */
+	for (i = 0; i < n_voltages; i++) {
+		ctrl_uV = regulator_list_voltage(ctrl_reg, i);
+
+		if (ctrl_uV < vrange_ctrl->min_uV ||
+		    ctrl_uV > vrange_ctrl->max_uV) {
+			rdesc->n_voltages--;
+			continue;
+		}
+	}
+
+	if (rdesc->n_voltages == 0) {
+		dev_err(&pdev->dev, "invalid configuration\n");
+		return -EINVAL;
+	}
+
+	vctrl->vtable = devm_kmalloc_array(
+		&pdev->dev, sizeof(struct vctrl_voltage_table),
+		rdesc->n_voltages, GFP_KERNEL | __GFP_ZERO);
+	if (!vctrl->vtable)
+		return -ENOMEM;
+
+	/* create mapping control <=> output voltage */
+	for (i = 0, idx_vt = 0; i < n_voltages; i++) {
+		ctrl_uV = regulator_list_voltage(ctrl_reg, i);
+
+		if (ctrl_uV < vrange_ctrl->min_uV ||
+		    ctrl_uV > vrange_ctrl->max_uV)
+			continue;
+
+		vctrl->vtable[idx_vt].ctrl = ctrl_uV;
+		vctrl->vtable[idx_vt].out =
+			vctrl_calc_output_voltage(vctrl, ctrl_uV);
+		idx_vt++;
+	}
+
+	/* we rely on the table to be ordered by ascending voltage */
+	sort(vctrl->vtable, rdesc->n_voltages,
+	     sizeof(struct vctrl_voltage_table), vctrl_cmp_ctrl_uV,
+	     NULL);
+
+	/* pre-calculate OVP-safe downward transitions */
+	for (i = n_voltages - 1; i > 0; i--) {
+		int j;
+		int ovp_min_uV = (vctrl->vtable[i].out *
+				  (100 - vctrl->ovp_threshold)) / 100;
+
+		for (j = 0; j < i; j++) {
+			if (vctrl->vtable[j].out >= ovp_min_uV) {
+				vctrl->vtable[i].ovp_min_sel = j;
+				break;
+			}
+		}
+
+		if (j == i) {
+			dev_warn(&pdev->dev, "switching down from %duV may cause OVP shutdown\n",
+				vctrl->vtable[i].out);
+			/* use next lowest voltage */
+			vctrl->vtable[i].ovp_min_sel = i - 1;
+		}
+	}
+
+	return 0;
+}
+
+static int vctrl_enable(struct regulator_dev *rdev)
+{
+	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
+	int ret = regulator_enable(vctrl->ctrl_reg);
+
+	if (!ret)
+		vctrl->enabled = true;
+
+	return ret;
+}
+
+static int vctrl_disable(struct regulator_dev *rdev)
+{
+	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
+	int ret = regulator_disable(vctrl->ctrl_reg);
+
+	if (!ret)
+		vctrl->enabled = false;
+
+	return ret;
+}
+
+static int vctrl_is_enabled(struct regulator_dev *rdev)
+{
+	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
+
+	return vctrl->enabled;
+}
+
+static const struct regulator_ops vctrl_ops_cont = {
+	.enable		  = vctrl_enable,
+	.disable	  = vctrl_disable,
+	.is_enabled	  = vctrl_is_enabled,
+	.get_voltage	  = vctrl_get_voltage,
+	.set_voltage	  = vctrl_set_voltage,
+};
+
+static const struct regulator_ops vctrl_ops_non_cont = {
+	.enable		  = vctrl_enable,
+	.disable	  = vctrl_disable,
+	.is_enabled	  = vctrl_is_enabled,
+	.set_voltage_sel = vctrl_set_voltage_sel,
+	.get_voltage_sel = vctrl_get_voltage_sel,
+	.list_voltage    = vctrl_list_voltage,
+	.map_voltage     = regulator_map_voltage_iterate,
+};
+
+static int vctrl_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct vctrl_data *vctrl;
+	const struct regulator_init_data *init_data;
+	struct regulator_desc *rdesc;
+	struct regulator_config cfg = { };
+	struct vctrl_voltage_range *vrange_ctrl;
+	int ctrl_uV;
+	int ret;
+
+	vctrl = devm_kzalloc(&pdev->dev, sizeof(struct vctrl_data),
+			     GFP_KERNEL);
+	if (!vctrl)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, vctrl);
+
+	ret = vctrl_parse_dt(pdev, vctrl);
+	if (ret)
+		return ret;
+
+	vrange_ctrl = &vctrl->vrange.ctrl;
+
+	rdesc = &vctrl->desc;
+	rdesc->name = "vctrl";
+	rdesc->type = REGULATOR_VOLTAGE;
+	rdesc->owner = THIS_MODULE;
+
+	if ((regulator_get_linear_step(vctrl->ctrl_reg) == 1) ||
+	    (regulator_count_voltages(vctrl->ctrl_reg) == -EINVAL)) {
+		rdesc->continuous_voltage_range = true;
+		rdesc->ops = &vctrl_ops_cont;
+	} else {
+		rdesc->ops = &vctrl_ops_non_cont;
+	}
+
+	init_data = of_get_regulator_init_data(&pdev->dev, np, rdesc);
+	if (!init_data)
+		return -ENOMEM;
+
+	cfg.of_node = np;
+	cfg.dev = &pdev->dev;
+	cfg.driver_data = vctrl;
+	cfg.init_data = init_data;
+
+	if (!rdesc->continuous_voltage_range) {
+		ret = vctrl_init_vtable(pdev);
+		if (ret)
+			return ret;
+
+		ctrl_uV = regulator_get_voltage(vctrl->ctrl_reg);
+		if (ctrl_uV < 0) {
+			dev_err(&pdev->dev, "failed to get control voltage\n");
+			return ctrl_uV;
+		}
+
+		/* determine current voltage selector from control voltage */
+		if (ctrl_uV < vrange_ctrl->min_uV) {
+			vctrl->sel = 0;
+		} else if (ctrl_uV > vrange_ctrl->max_uV) {
+			vctrl->sel = rdesc->n_voltages - 1;
+		} else {
+			int i;
+
+			for (i = 0; i < rdesc->n_voltages; i++) {
+				if (ctrl_uV == vctrl->vtable[i].ctrl) {
+					vctrl->sel = i;
+					break;
+				}
+			}
+		}
+	}
+
+	vctrl->rdev = devm_regulator_register(&pdev->dev, rdesc, &cfg);
+	if (IS_ERR(vctrl->rdev)) {
+		ret = PTR_ERR(vctrl->rdev);
+		dev_err(&pdev->dev, "failed to register regulator: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id vctrl_of_match[] = {
+	{ .compatible = "vctrl-regulator", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, vctrl_of_match);
+
+static struct platform_driver vctrl_driver = {
+	.probe		= vctrl_probe,
+	.driver		= {
+		.name		= "vctrl-regulator",
+		.of_match_table = of_match_ptr(vctrl_of_match),
+	},
+};
+
+module_platform_driver(vctrl_driver);
+
+MODULE_DESCRIPTION("Voltage Controlled Regulator Driver");
+MODULE_AUTHOR("Matthias Kaehlcke <mka-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH] ARM: dts: stm32f7: add STM32f769I & stm32f746 discovery board support
From: Vikas Manocha @ 2017-04-10 18:40 UTC (permalink / raw)
  To: Alexandre Torgue, patrice.chotard-qxv4g6HH51o
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM PORT, open list, Mark Rutland, Maxime Coquelin,
	Rob Herring, Russell King
In-Reply-To: <6ea617a3-94bc-870f-dd52-a45ad45c6d26-qxv4g6HH51o@public.gmane.org>

Thanks Alex,

On 04/10/2017 12:23 AM, Alexandre Torgue wrote:
> Hi
> 
> On 04/08/2017 03:12 AM, Vikas Manocha wrote:
>> Stm32f769I & stm32f746 are MCUs of stm32f7 family. Here are the major
>> spces of the two boards:
>>
>> stm32f769I discovery board:
>>     - Cortex-M7 core @216MHz
>>     - 2MB mcu internal flash
>>     - 512KB internal sram
>>     - 16MB sdram memory
>>     - 64MB qspi flash memory
>>     - 4 inch wvga LCD-TFT Display
>>
>> stm32f746 discovery board:
>>     - Cortex-M7 core @216MHz
>>     - 1MB mcu internal flash
>>     - 320KB internal sram
>>     - 8MB sdram memory
>>     - 16MB qspi flash memory
>>     - 4.3 inch 480x272 LCD-TFT display
>>
>> Signed-off-by: Vikas Manocha <vikas.manocha-qxv4g6HH51o@public.gmane.org>
>> ---
>>  arch/arm/boot/dts/Makefile            |   2 +
>>  arch/arm/boot/dts/stm32f746-disco.dts | 101 ++++++++++++++++++++++++++++++++++
>>  arch/arm/boot/dts/stm32f746.dtsi      |   2 +-
>>  arch/arm/boot/dts/stm32f769-disco.dts | 101 ++++++++++++++++++++++++++++++++++
>>  4 files changed, 205 insertions(+), 1 deletion(-)
>>  create mode 100644 arch/arm/boot/dts/stm32f746-disco.dts
>>  create mode 100644 arch/arm/boot/dts/stm32f769-disco.dts
>>
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index 0118084..a119f74 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -763,6 +763,8 @@ dtb-$(CONFIG_ARCH_STI) += \
>>  dtb-$(CONFIG_ARCH_STM32)+= \
>>      stm32f429-disco.dtb \
>>      stm32f469-disco.dtb \
>> +    stm32f746-disco.dtb \
>> +    stm32f769-disco.dtb \
>>      stm32429i-eval.dtb \
>>      stm32746g-eval.dtb
>>  dtb-$(CONFIG_MACH_SUN4I) += \
>> diff --git a/arch/arm/boot/dts/stm32f746-disco.dts b/arch/arm/boot/dts/stm32f746-disco.dts
>> new file mode 100644
>> index 0000000..c0e313f
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/stm32f746-disco.dts
>> @@ -0,0 +1,101 @@
>> +/*
>> + * Copyright 2017 - Vikas MANOCHA <vikas.manocha-qxv4g6HH51o@public.gmane.org>
>> + *
>> + * This file is dual-licensed: you can use it either under the terms
>> + * of the GPL or the X11 license, at your option. Note that this dual
>> + * licensing only applies to this file, and not this project as a
>> + * whole.
>> + *
>> + *  a) This file 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; either version 2 of the
>> + *     License, or (at your option) any later version.
>> + *
>> + *     This file 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.
>> + *
>> + * Or, alternatively,
>> + *
>> + *  b) Permission is hereby granted, free of charge, to any person
>> + *     obtaining a copy of this software and associated documentation
>> + *     files (the "Software"), to deal in the Software without
>> + *     restriction, including without limitation the rights to use,
>> + *     copy, modify, merge, publish, distribute, sublicense, and/or
>> + *     sell copies of the Software, and to permit persons to whom the
>> + *     Software is furnished to do so, subject to the following
>> + *     conditions:
>> + *
>> + *     The above copyright notice and this permission notice shall be
>> + *     included in all copies or substantial portions of the Software.
>> + *
>> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
>> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + *     OTHER DEALINGS IN THE SOFTWARE.
>> + */
>> +
>> +/dts-v1/;
>> +#include "stm32f746.dtsi"
>> +#include <dt-bindings/input/input.h>
>> +
>> +/ {
>> +    model = "STMicroelectronics STM32F746-DISCO board";
>> +    compatible = "st,stm32f746-disco", "st,stm32f746";
>> +
>> +    chosen {
>> +        bootargs = "root=/dev/ram";
>> +        stdout-path = "serial0:115200n8";
>> +    };
>> +
>> +    memory {
>> +        reg = <0xC0000000 0x800000>;
>> +    };
>> +
>> +    aliases {
>> +        serial0 = &usart1;
>> +    };
>> +
>> +};
>> +
>> +&clk_hse {
>> +    clock-frequency = <25000000>;
>> +};
>> +
>> +&pinctrl {
> 
> 
> Pin muxing is not defined in board file. Please move it into SOC dtsi file.

Pin muxing used is different for different boards. e.g. usart1_rx pad is PA10 for stm32f769-disco board while it is PB7 for stm32f746-disco board. 
The other possibilities for same pad (usart1_rx) is PB15. To make situation bit more complex, it is only available in f769 device.

Putting in SOC dtsi file means having lot of combinations for different pins in separate groups. 
e.g. only for one instance of one ip (usart1), following groups might be required at one point of time:

usart1_pa10_pa9 {..}
usart1_pa10_pb14 {..}
usart1_pa10_pb6 {..}

usart1_pb7_pa9 {..}
usart1_pb7_pb14 {..}
usart1_pb7_pb6 {..}

usart1_pb15_pa9 {..}
usart1_pb15_pb14 {..}
usart1_pb15_pb6 {..}

In case of boards based on stm32f746 device, all the above mentioned groups with pb14 & pb15 will not be available.
One solution (to avoid using not available groups) could be to have separate dtsi (or separate pinmux.dtsi) for different devices of same family like one for stm32f746 & other for stm32f769. Still it does not resolve the need to have lot of groups combinations for each instance of every peripheral in dtsi as mentioned above.

It seems cleaner solution would be pin muxing in board dts file. Please let me know if there is some drawback of this approach. One point which i can think of is : duplication of pinmux groups in different board dts files.

Cheers,
Vikas

>> +    usart1_pins: usart1@0    {
>> +        pins1 {
>> +            pinmux = <STM32F746_PA9_FUNC_USART1_TX>;
>> +                bias-disable;
>> +                drive-push-pull;
>> +                slew-rate = <2>;
>> +        };
>> +        pins2 {
>> +            pinmux = <STM32F746_PB7_FUNC_USART1_RX>;
>> +            bias-disable;
>> +        };
>> +    };
>> +
>> +    qspi_pins: qspi@0 {
>> +        pins {
>> +            pinmux = <STM32F746_PB2_FUNC_QUADSPI_CLK>,
>> +                   <STM32F746_PB6_FUNC_QUADSPI_BK1_NCS>,
>> +                   <STM32F746_PD11_FUNC_QUADSPI_BK1_IO0>,
>> +                   <STM32F746_PD12_FUNC_QUADSPI_BK1_IO1>,
>> +                   <STM32F746_PD13_FUNC_QUADSPI_BK1_IO3>,
>> +                   <STM32F746_PE2_FUNC_QUADSPI_BK1_IO2>;
>> +            slew-rate = <2>;
>> +        };
>> +    };
>> +};
>> +
>> +&usart1 {
>> +    pinctrl-0 = <&usart1_pins>;
>> +    pinctrl-names = "default";
>> +    status = "okay";
>> +};
>> diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/stm32f746.dtsi
>> index f321ffe..826700f 100644
>> --- a/arch/arm/boot/dts/stm32f746.dtsi
>> +++ b/arch/arm/boot/dts/stm32f746.dtsi
>> @@ -178,7 +178,7 @@
>>              interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>;
>>          };
>>
>> -        pin-controller {
>> +        pinctrl: pin-controller {
>>              #address-cells = <1>;
>>              #size-cells = <1>;
>>              compatible = "st,stm32f746-pinctrl";
>> diff --git a/arch/arm/boot/dts/stm32f769-disco.dts b/arch/arm/boot/dts/stm32f769-disco.dts
>> new file mode 100644
>> index 0000000..5f8558e
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/stm32f769-disco.dts
>> @@ -0,0 +1,101 @@
>> +/*
>> + * Copyright 2017 - Vikas MANOCHA <vikas.manocha-qxv4g6HH51o@public.gmane.org>
>> + *
>> + * This file is dual-licensed: you can use it either under the terms
>> + * of the GPL or the X11 license, at your option. Note that this dual
>> + * licensing only applies to this file, and not this project as a
>> + * whole.
>> + *
>> + *  a) This file 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; either version 2 of the
>> + *     License, or (at your option) any later version.
>> + *
>> + *     This file 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.
>> + *
>> + * Or, alternatively,
>> + *
>> + *  b) Permission is hereby granted, free of charge, to any person
>> + *     obtaining a copy of this software and associated documentation
>> + *     files (the "Software"), to deal in the Software without
>> + *     restriction, including without limitation the rights to use,
>> + *     copy, modify, merge, publish, distribute, sublicense, and/or
>> + *     sell copies of the Software, and to permit persons to whom the
>> + *     Software is furnished to do so, subject to the following
>> + *     conditions:
>> + *
>> + *     The above copyright notice and this permission notice shall be
>> + *     included in all copies or substantial portions of the Software.
>> + *
>> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
>> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
>> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
>> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
>> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + *     OTHER DEALINGS IN THE SOFTWARE.
>> + */
>> +
>> +/dts-v1/;
>> +#include "stm32f746.dtsi"
>> +#include <dt-bindings/input/input.h>
>> +
>> +/ {
>> +    model = "STMicroelectronics STM32F769-DISCO board";
>> +    compatible = "st,stm32f769-disco", "st,stm32f7";
>> +
>> +    chosen {
>> +        bootargs = "root=/dev/ram";
>> +        stdout-path = "serial0:115200n8";
>> +    };
>> +
>> +    memory {
>> +        reg = <0xC0000000 0x1000000>;
>> +    };
>> +
>> +    aliases {
>> +        serial0 = &usart1;
>> +    };
>> +
>> +};
>> +
>> +&clk_hse {
>> +    clock-frequency = <25000000>;
>> +};
>> +
>> +&pinctrl {
> 
> same.
> 
>> +    usart1_pins: usart1@0    {
>> +        pins1 {
>> +            pinmux = <STM32F746_PA9_FUNC_USART1_TX>;
>> +                bias-disable;
>> +                drive-push-pull;
>> +                slew-rate = <2>;
>> +        };
>> +        pins2 {
>> +            pinmux = <STM32F746_PA10_FUNC_USART1_RX>;
>> +            bias-disable;
>> +        };
>> +    };
>> +
>> +    qspi_pins: qspi@0 {
>> +        pins {
>> +            pinmux = <STM32F746_PB2_FUNC_QUADSPI_CLK>,
>> +                   <STM32F746_PB6_FUNC_QUADSPI_BK1_NCS>,
>> +                   <STM32F746_PC9_FUNC_QUADSPI_BK1_IO0>,
>> +                   <STM32F746_PC10_FUNC_QUADSPI_BK1_IO1>,
>> +                   <STM32F746_PD13_FUNC_QUADSPI_BK1_IO3>,
>> +                   <STM32F746_PE2_FUNC_QUADSPI_BK1_IO2>;
>> +            slew-rate = <2>;
>> +        };
>> +    };
>> +};
>> +
>> +&usart1 {
>> +    pinctrl-0 = <&usart1_pins>;
>> +    pinctrl-names = "default";
>> +    status = "okay";
>> +};
>>
> .
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 3/3] dt-bindings: Document Phytec phyCORE-RK3288 RDK
From: Rob Herring @ 2017-04-10 18:26 UTC (permalink / raw)
  To: Wadim Egorov
  Cc: mark.rutland-5wv7dgnIgG8, heiko-4mtYJXux2i+zQB+pC5nmwQ,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1491483866-18368-3-git-send-email-w.egorov-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>

On Thu, Apr 06, 2017 at 03:04:26PM +0200, Wadim Egorov wrote:
> Add documentation for the PCM-947 carrier board, a RK3288 based
> development board made by PHYTEC.
> 
> Signed-off-by: Wadim Egorov <w.egorov-guT5V/WYfQezQB+pC5nmwQ@public.gmane.org>
> ---
> No changes in v2
> ---
>  Documentation/devicetree/bindings/arm/rockchip.txt | 4 ++++
>  1 file changed, 4 insertions(+)

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v5 1/5] dt-bindings: watchdog: Document STM32 IWDG bindings
From: Rob Herring @ 2017-04-10 18:25 UTC (permalink / raw)
  To: Yannick Fertre
  Cc: Wim Van Sebroeck, Guenter Roeck, Alexandre TORGUE,
	Benjamin Gaignard, Maxime Coquelin,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Philippe Cornu,
	Gabriel FERNANDEZ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1491481168-22213-2-git-send-email-yannick.fertre-qxv4g6HH51o@public.gmane.org>

On Thu, Apr 06, 2017 at 02:19:24PM +0200, Yannick Fertre wrote:
> This adds documentation of device tree bindings for the STM32 IWDG
> (Independent WatchDoG).
> 
> Signed-off-by: Yannick Fertre <yannick.fertre-qxv4g6HH51o@public.gmane.org>
> ---
>  .../devicetree/bindings/watchdog/st,stm32-iwdg.txt    | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] of: Add vendor prefix for Nordic Semiconductor
From: Rob Herring @ 2017-04-10 18:24 UTC (permalink / raw)
  To: Kumar Gala; +Cc: Device Tree Mailing List, Mark Rutland
In-Reply-To: <20170406082927.31405-1-kumar.gala-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Thu, Apr 06, 2017 at 03:29:27AM -0500, Kumar Gala wrote:
> Nordic Semiconductor is a semiconductor company specializing in ARM
> Cortex-M based SoCs for low-power wireless communication, especially
> Bluetooth.
> 
> Signed-off-by: Kumar Gala <kumar.gala-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)

Applied, thanks.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply


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