linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/18] FSI device driver introduction
@ 2017-02-01 16:53 Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 01/18] drivers/fsi: Add empty fsi bus definitions Christopher Bostic
                   ` (17 more replies)
  0 siblings, 18 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Christopher Bostic

Introduction of the IBM 'Flexible Support Interface' (FSI) bus device
driver. FSI is a high fan out serial bus consisting of a clock and a serial
data line capable of running at speeds up to 166 MHz.

This set provides the basic framework to add FSI extensions to the
Linux bus and device models. Master specific implementations are
defined to utilize the core FSI function.

In Linux, we have a core FSI "bus type", along with drivers for FSI
masters and engines.

The FSI master drivers expose a read/write interface to the bus address
space. The master drivers are under drivers/fsi/fsi-master-*.c.

The core handles probing and discovery of slaves and slave
engines, using those read/write interfaces. It is responsible for
creating the endpoint Linux devices corresponding to the discovered
engines on each slave.

Slave engines are identified by an 'engine' type, and an optional
version. Engine, a.k.a. client, drivers are matched and bound to these
engines during discovery.

This patch set does not include extended FSI function such as:
    *  Hub master support
    *  Cascaded master support
    *  Application layer hot plug notification
    *  Application layer FSI bus status interface

Common FSI terminology:

* Master
    Controller of the FSI bus.  Only the master is allowed to control the
    clock line and is the initiator of all transactions on a bus.

* Slave
    The receiver or target of a master initiated transaction.  The slave
    cannot initiate communications on a bus and must respond to any
    master requests for data.

* CFAM
    Stands for Common Field replaceable unit Access Macro.  A CFAM is an
    ASIC residing in any device requiring FSI communications. CFAMs
    consist of an array of hardware 'engines' used for various purposes.
    I2C masters, UARTs, General Purpose IO hardware are common types of
    these engines.

* Configuration Space / Table
    A table contained at the beginning of each CFAM address space.
    This table lists information such as the CFAM's ID, which engine types
    and versions it has available, as well as its addressing range.

* FSI Engine driver
    A device driver that registers with the FSI core so that it can access
    devices it owns on an FSI bus.

Chris Bostic (8):
  drivers/fsi: Kick off master scan via sysfs
  drivers/fsi: Set up links for slave communication
  drivers/fsi: Set slave SMODE to init communication
  drivers/fsi: Remove all scanned devices during master unregister
  drivers/fsi: Add FSI bus documentation
  drivers/fsi: Add documentation for GPIO based FSI master
  drivers/fsi: Document FSI master sysfs files in ABI
  drivers/fsi: Add GPIO based FSI master

Jeremy Kerr (10):
  drivers/fsi: Add empty fsi bus definitions
  drivers/fsi: Add device & driver definitions
  drivers/fsi: add driver to device matches
  drivers/fsi: Add fsi master definition
  drivers/fsi: Add slave definition
  drivers/fsi: Add empty master scan
  drivers/fsi: Add FSI crc calculators to library
  drivers/fsi: Implement slave initialisation
  drivers/fsi: scan slaves & register devices
  drivers/fsi: Add device read/write/peek functions

 Documentation/ABI/testing/sysfs-bus-fsi            |   6 +
 .../devicetree/bindings/fsi/fsi-master-gpio.txt    |  71 +++
 Documentation/devicetree/bindings/fsi/fsi.txt      |  54 +++
 drivers/Kconfig                                    |   2 +
 drivers/Makefile                                   |   1 +
 drivers/fsi/Kconfig                                |  23 +
 drivers/fsi/Makefile                               |   3 +
 drivers/fsi/fsi-core.c                             | 494 +++++++++++++++++++
 drivers/fsi/fsi-master-gpio.c                      | 530 +++++++++++++++++++++
 drivers/fsi/fsi-master.h                           |  39 ++
 include/linux/crc-fsi.h                            |  29 ++
 include/linux/fsi.h                                |  60 +++
 lib/Makefile                                       |   1 +
 lib/crc-fsi.c                                      |  39 ++
 14 files changed, 1352 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-fsi
 create mode 100644 Documentation/devicetree/bindings/fsi/fsi-master-gpio.txt
 create mode 100644 Documentation/devicetree/bindings/fsi/fsi.txt
 create mode 100644 drivers/fsi/Kconfig
 create mode 100644 drivers/fsi/Makefile
 create mode 100644 drivers/fsi/fsi-core.c
 create mode 100644 drivers/fsi/fsi-master-gpio.c
 create mode 100644 drivers/fsi/fsi-master.h
 create mode 100644 include/linux/crc-fsi.h
 create mode 100644 include/linux/fsi.h
 create mode 100644 lib/crc-fsi.c

-- 
1.8.2.2

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

* [PATCH v3 01/18] drivers/fsi: Add empty fsi bus definitions
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-23 10:53   ` Geert Uytterhoeven
  2017-02-01 16:53 ` [PATCH v3 02/18] drivers/fsi: Add device & driver definitions Christopher Bostic
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

From: Jeremy Kerr <jk@ozlabs.org>

This change adds the initial (empty) fsi bus definition, and introduces
drivers/fsi/.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 drivers/Kconfig        |  2 ++
 drivers/Makefile       |  1 +
 drivers/fsi/Kconfig    | 12 ++++++++++++
 drivers/fsi/Makefile   |  2 ++
 drivers/fsi/fsi-core.c | 38 ++++++++++++++++++++++++++++++++++++++
 include/linux/fsi.h    | 22 ++++++++++++++++++++++
 6 files changed, 77 insertions(+)
 create mode 100644 drivers/fsi/Kconfig
 create mode 100644 drivers/fsi/Makefile
 create mode 100644 drivers/fsi/fsi-core.c
 create mode 100644 include/linux/fsi.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index e1e2066..117ca14c 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -202,4 +202,6 @@ source "drivers/hwtracing/intel_th/Kconfig"
 
 source "drivers/fpga/Kconfig"
 
+source "drivers/fsi/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index f0afdfb..126e109 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -173,3 +173,4 @@ obj-$(CONFIG_STM)		+= hwtracing/stm/
 obj-$(CONFIG_ANDROID)		+= android/
 obj-$(CONFIG_NVMEM)		+= nvmem/
 obj-$(CONFIG_FPGA)		+= fpga/
+obj-$(CONFIG_FSI)		+= fsi/
diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
new file mode 100644
index 0000000..04c1a0e
--- /dev/null
+++ b/drivers/fsi/Kconfig
@@ -0,0 +1,12 @@
+#
+# FSI subsystem
+#
+
+menu "FSI support"
+
+config FSI
+	tristate "FSI support"
+	---help---
+	  FSI - the FRU Support Interface - is a simple bus for low-level
+	  access to POWER-based hardware.
+endmenu
diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
new file mode 100644
index 0000000..db0e5e7
--- /dev/null
+++ b/drivers/fsi/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_FSI) += fsi-core.o
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
new file mode 100644
index 0000000..3e45306
--- /dev/null
+++ b/drivers/fsi/fsi-core.c
@@ -0,0 +1,38 @@
+/*
+ * FSI core driver
+ *
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/fsi.h>
+#include <linux/module.h>
+
+/* FSI core & Linux bus type definitions */
+
+struct bus_type fsi_bus_type = {
+	.name		= "fsi",
+};
+EXPORT_SYMBOL_GPL(fsi_bus_type);
+
+static int fsi_init(void)
+{
+	return bus_register(&fsi_bus_type);
+}
+
+static void fsi_exit(void)
+{
+	bus_unregister(&fsi_bus_type);
+}
+
+module_init(fsi_init);
+module_exit(fsi_exit);
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
new file mode 100644
index 0000000..47aa181
--- /dev/null
+++ b/include/linux/fsi.h
@@ -0,0 +1,22 @@
+/* FSI device & driver interfaces
+ *
+ * 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 LINUX_FSI_H
+#define LINUX_FSI_H
+
+#include <linux/device.h>
+
+extern struct bus_type fsi_bus_type;
+
+#endif /* LINUX_FSI_H */
-- 
1.8.2.2

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

* [PATCH v3 02/18] drivers/fsi: Add device & driver definitions
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 01/18] drivers/fsi: Add empty fsi bus definitions Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 03/18] drivers/fsi: add driver to device matches Christopher Bostic
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

From: Jeremy Kerr <jk@ozlabs.org>

Add structs for fsi devices & drivers, and struct device conversion
functions.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 include/linux/fsi.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index 47aa181..f73886a 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -17,6 +17,17 @@
 
 #include <linux/device.h>
 
+struct fsi_device {
+	struct device dev;
+};
+
+struct fsi_driver {
+	struct device_driver drv;
+};
+
+#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 struct bus_type fsi_bus_type;
 
 #endif /* LINUX_FSI_H */
-- 
1.8.2.2

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

* [PATCH v3 03/18] drivers/fsi: add driver to device matches
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 01/18] drivers/fsi: Add empty fsi bus definitions Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 02/18] drivers/fsi: Add device & driver definitions Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 04/18] drivers/fsi: Add fsi master definition Christopher Bostic
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

From: Jeremy Kerr <jk@ozlabs.org>

Driver bind to devices based on the engine types & (optional) versions.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 drivers/fsi/fsi-core.c | 21 +++++++++++++++++++++
 include/linux/fsi.h    | 21 +++++++++++++++++++--
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 3e45306..3d55bd5 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -19,8 +19,29 @@
 
 /* FSI core & Linux bus type definitions */
 
+static int fsi_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct fsi_device *fsi_dev = to_fsi_dev(dev);
+	struct fsi_driver *fsi_drv = to_fsi_drv(drv);
+	const struct fsi_device_id *id;
+
+	if (!fsi_drv->id_table)
+		return 0;
+
+	for (id = fsi_drv->id_table; id->engine_type; id++) {
+		if (id->engine_type != fsi_dev->engine_type)
+			continue;
+		if (id->version == FSI_VERSION_ANY ||
+				id->version == fsi_dev->version)
+			return 1;
+	}
+
+	return 0;
+}
+
 struct bus_type fsi_bus_type = {
 	.name		= "fsi",
+	.match		= fsi_bus_match,
 };
 EXPORT_SYMBOL_GPL(fsi_bus_type);
 
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index f73886a..273cbf6 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -18,11 +18,28 @@
 #include <linux/device.h>
 
 struct fsi_device {
-	struct device dev;
+	struct device		dev;
+	u8			engine_type;
+	u8			version;
 };
 
+struct fsi_device_id {
+	u8	engine_type;
+	u8	version;
+};
+
+#define FSI_VERSION_ANY		0
+
+#define FSI_DEVICE(t) \
+	.engine_type = (t), .version = FSI_VERSION_ANY,
+
+#define FSI_DEVICE_VERSIONED(t, v) \
+	.engine_type = (t), .version = (v),
+
+
 struct fsi_driver {
-	struct device_driver drv;
+	struct device_driver		drv;
+	const struct fsi_device_id	*id_table;
 };
 
 #define to_fsi_dev(devp) container_of(devp, struct fsi_device, dev)
-- 
1.8.2.2

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

* [PATCH v3 04/18] drivers/fsi: Add fsi master definition
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (2 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 03/18] drivers/fsi: add driver to device matches Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-10 14:21   ` Greg KH
  2017-02-01 16:53 ` [PATCH v3 05/18] drivers/fsi: Add slave definition Christopher Bostic
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

From: Jeremy Kerr <jk@ozlabs.org>

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 drivers/fsi/fsi-core.c   | 28 ++++++++++++++++++++++++++++
 drivers/fsi/fsi-master.h | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 65 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..c7469fe 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -16,6 +16,34 @@
 #include <linux/device.h>
 #include <linux/fsi.h>
 #include <linux/module.h>
+#include <linux/idr.h>
+
+#include "fsi-master.h"
+
+static DEFINE_IDA(master_ida);
+
+/* FSI master support */
+
+int fsi_master_register(struct fsi_master *master)
+{
+	if (!master || !master->dev)
+		return -EINVAL;
+
+	master->idx = ida_simple_get(&master_ida, 0, 0, GFP_KERNEL);
+	get_device(master->dev);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fsi_master_register);
+
+void fsi_master_unregister(struct fsi_master *master)
+{
+	if (!master || !master->dev)
+		return;
+
+	ida_simple_remove(&master_ida, master->idx);
+	put_device(master->dev);
+}
+EXPORT_SYMBOL_GPL(fsi_master_unregister);
 
 /* FSI core & Linux bus type definitions */
 
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
new file mode 100644
index 0000000..e75a810
--- /dev/null
+++ b/drivers/fsi/fsi-master.h
@@ -0,0 +1,37 @@
+/*
+ * 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		(*read)(struct fsi_master *, int link,
+				uint8_t slave, uint32_t addr,
+				void *val, size_t size);
+	int		(*write)(struct fsi_master *, int link,
+				uint8_t slave, uint32_t addr,
+				const void *val, size_t size);
+};
+
+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

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

* [PATCH v3 05/18] drivers/fsi: Add slave definition
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (3 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 04/18] drivers/fsi: Add fsi master definition Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 06/18] drivers/fsi: Add empty master scan Christopher Bostic
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

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@us.ibm.com>
---
 drivers/fsi/fsi-core.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index c7469fe..78d9c558 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -22,6 +22,15 @@
 
 static DEFINE_IDA(master_ida);
 
+struct fsi_slave {
+	struct device		dev;
+	struct fsi_master	*master;
+	int			link;
+	uint8_t			id;
+};
+
+#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	[flat|nested] 24+ messages in thread

* [PATCH v3 06/18] drivers/fsi: Add empty master scan
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (4 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 05/18] drivers/fsi: Add slave definition Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 07/18] drivers/fsi: Add FSI crc calculators to library Christopher Bostic
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

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@us.ibm.com>
---
 drivers/fsi/fsi-core.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 78d9c558..3160c1c 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -20,6 +20,8 @@
 
 #include "fsi-master.h"
 
+#define FSI_N_SLAVES	4
+
 static DEFINE_IDA(master_ida);
 
 struct fsi_slave {
@@ -31,8 +33,29 @@ 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 slave_id)
+{
+	/* todo: initialise slave device, perform engine scan */
+
+	return -ENODEV;
+}
+
 /* FSI master support */
 
+static int fsi_master_scan(struct fsi_master *master)
+{
+	int link, slave_id;
+
+	for (link = 0; link < master->n_links; link++)
+		for (slave_id = 0; slave_id < FSI_N_SLAVES; slave_id++)
+			fsi_slave_init(master, link, slave_id);
+
+	return 0;
+
+}
+
 int fsi_master_register(struct fsi_master *master)
 {
 	if (!master || !master->dev)
@@ -40,6 +63,7 @@ int fsi_master_register(struct fsi_master *master)
 
 	master->idx = ida_simple_get(&master_ida, 0, 0, GFP_KERNEL);
 	get_device(master->dev);
+	fsi_master_scan(master);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(fsi_master_register);
-- 
1.8.2.2

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

* [PATCH v3 07/18] drivers/fsi: Add FSI crc calculators to library
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (5 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 06/18] drivers/fsi: Add empty master scan Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 08/18] drivers/fsi: Kick off master scan via sysfs Christopher Bostic
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

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.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 include/linux/crc-fsi.h | 29 +++++++++++++++++++++++++++++
 lib/Makefile            |  1 +
 lib/crc-fsi.c           | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+)
 create mode 100644 include/linux/crc-fsi.h
 create mode 100644 lib/crc-fsi.c

diff --git a/include/linux/crc-fsi.h b/include/linux/crc-fsi.h
new file mode 100644
index 0000000..e96d2f0
--- /dev/null
+++ b/include/linux/crc-fsi.h
@@ -0,0 +1,29 @@
+/*
+ * FSI CRC calculator
+ *
+ * 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.
+ *
+ *
+ * Implements the standard FSI CRC:
+ *
+ *   Width 1 - 32
+ *   Poly  0x0017 (x^4 + x^2 + x^1 + x^0)
+ */
+
+#ifndef CRC_FSI_H
+#define CRC_FSI_H
+
+#include <linux/types.h>
+
+uint8_t crc_fsi(uint8_t c, uint64_t x, int bits);
+
+#endif /* CRC_FSI_H */
diff --git a/lib/Makefile b/lib/Makefile
index 50144a3..c840628 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -230,3 +230,4 @@ obj-$(CONFIG_UBSAN) += ubsan.o
 UBSAN_SANITIZE_ubsan.o := n
 
 obj-$(CONFIG_SBITMAP) += sbitmap.o
+obj-$(CONFIG_FSI) += crc-fsi.o
diff --git a/lib/crc-fsi.c b/lib/crc-fsi.c
new file mode 100644
index 0000000..55cfe9d
--- /dev/null
+++ b/lib/crc-fsi.c
@@ -0,0 +1,39 @@
+/*
+ * FSI CRC calculator
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crc-fsi.h>
+
+/* crc helpers */
+static const uint8_t crc_fsi_tab[] = {
+	0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
+	0x1, 0x6, 0xf, 0x8, 0xa, 0xd, 0x4, 0x3,
+};
+
+uint8_t crc_fsi(uint8_t c, uint64_t x, int bits)
+{
+	int i;
+
+	/* Align to 4-bits */
+	bits = (bits + 3) & ~0x3;
+
+	/* Calculate crc4 over four-bit nibbles, starting at the MSbit */
+	for (i = bits; i >= 0; i -= 4)
+		c = crc_fsi_tab[c ^ ((x >> i) & 0xf)];
+
+	return c;
+}
+EXPORT_SYMBOL_GPL(crc_fsi);
-- 
1.8.2.2

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

* [PATCH v3 08/18] drivers/fsi: Kick off master scan via sysfs
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (6 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 07/18] drivers/fsi: Add FSI crc calculators to library Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 09/18] drivers/fsi: Implement slave initialisation Christopher Bostic
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Chris Bostic

From: Chris Bostic <cbostic@us.ibm.com>

Move master scan from automatic kick off early in kernel power up
to a scan file that can be invoked at any particular time based
on needs of a given platform.

Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 drivers/fsi/fsi-core.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 3160c1c..5f9f7a9 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -53,8 +53,19 @@ static int fsi_master_scan(struct fsi_master *master)
 			fsi_slave_init(master, link, slave_id);
 
 	return 0;
+}
+
+static ssize_t store_scan(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf,
+				size_t count)
+{
+	struct fsi_master *master = dev_get_drvdata(dev);
 
+	fsi_master_scan(master);
+	return count;
 }
+static DEVICE_ATTR(scan, 0200, NULL, store_scan);
 
 int fsi_master_register(struct fsi_master *master)
 {
@@ -63,8 +74,8 @@ int fsi_master_register(struct fsi_master *master)
 
 	master->idx = ida_simple_get(&master_ida, 0, 0, GFP_KERNEL);
 	get_device(master->dev);
-	fsi_master_scan(master);
-	return 0;
+	dev_set_drvdata(master->dev, master);
+	return device_create_file(master->dev, &dev_attr_scan);
 }
 EXPORT_SYMBOL_GPL(fsi_master_register);
 
-- 
1.8.2.2

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

* [PATCH v3 09/18] drivers/fsi: Implement slave initialisation
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (7 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 08/18] drivers/fsi: Kick off master scan via sysfs Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 10/18] drivers/fsi: scan slaves & register devices Christopher Bostic
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

From: Jeremy Kerr <jk@ozlabs.org>

Create fsi_slave devices during the master scan.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 drivers/fsi/fsi-core.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 5f9f7a9..931bcba 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -17,10 +17,15 @@
 #include <linux/fsi.h>
 #include <linux/module.h>
 #include <linux/idr.h>
+#include <linux/crc-fsi.h>
+#include <linux/slab.h>
 
 #include "fsi-master.h"
 
 #define FSI_N_SLAVES	4
+#define FSI_SLAVE_CONF_CRC_SHIFT        4
+#define FSI_SLAVE_CONF_CRC_MASK         0x0000000f
+#define FSI_SLAVE_CONF_DATA_BITS        28
 
 static DEFINE_IDA(master_ida);
 
@@ -34,12 +39,59 @@ struct fsi_slave {
 #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
 
 /* FSI slave support */
+
+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 slave_id)
 {
-	/* todo: initialise slave device, perform engine scan */
+	struct fsi_slave *slave;
+	uint32_t chip_id;
+	int rc;
+	uint8_t crc;
+
+	rc = master->read(master, link, slave_id, 0, &chip_id, sizeof(chip_id));
+	if (rc) {
+		dev_warn(master->dev, "can't read slave %02x:%02x: %d\n",
+				link, slave_id, rc);
+		return -ENODEV;
+	}
+	crc = crc_fsi(0, chip_id >> FSI_SLAVE_CONF_CRC_SHIFT,
+			FSI_SLAVE_CONF_DATA_BITS);
+	if (crc != (chip_id & FSI_SLAVE_CONF_CRC_MASK)) {
+		dev_warn(master->dev, "slave %02x:%02x invalid chip id CRC!\n",
+				link, slave_id);
+		return -EIO;
+	}
+
+	pr_debug("fsi: found chip %08x at %02x:%02x:%02x\n",
+			master->idx, chip_id, link, slave_id);
+
+	/* we can communicate with a slave; create devices and scan */
+	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
+	if (!slave)
+		return -ENOMEM;
+
+	slave->master = master;
+	slave->id = slave_id;
+	slave->dev.parent = master->dev;
+	slave->dev.release = fsi_slave_release;
+
+	dev_set_name(&slave->dev, "slave@%02x:%02x", link, slave_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;
+	}
 
-	return -ENODEV;
+	return rc;
 }
 
 /* FSI master support */
-- 
1.8.2.2

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

* [PATCH v3 10/18] drivers/fsi: scan slaves & register devices
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (8 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 09/18] drivers/fsi: Implement slave initialisation Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 11/18] drivers/fsi: Add device read/write/peek functions Christopher Bostic
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

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@us.ibm.com>

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 drivers/fsi/fsi-core.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/fsi.h    |   4 ++
 2 files changed, 136 insertions(+), 4 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 931bcba..f7ef993 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -23,9 +23,19 @@
 #include "fsi-master.h"
 
 #define FSI_N_SLAVES	4
-#define FSI_SLAVE_CONF_CRC_SHIFT        4
-#define FSI_SLAVE_CONF_CRC_MASK         0x0000000f
-#define FSI_SLAVE_CONF_DATA_BITS        28
+
+#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;
 
 static DEFINE_IDA(master_ida);
 
@@ -38,8 +48,125 @@ struct fsi_slave {
 
 #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
 
+/* 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;
+}
+
 /* FSI slave support */
 
+static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
+			void *val, size_t size)
+{
+	return slave->master->read(slave->master, slave->link,
+			slave->id, 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;
+		}
+
+		crc = crc_fsi(0, conf >> FSI_SLAVE_CONF_CRC_SHIFT,
+				FSI_SLAVE_CONF_DATA_BITS);
+		if (crc != (conf & FSI_SLAVE_CONF_CRC_MASK)) {
+			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) {
+
+			/* 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);
+
+			device_initialize(&dev->dev);
+			dev_set_name(&dev->dev, "%02x:%02x:%02x:%02x",
+					slave->master->idx, slave->link,
+					slave->id, i - 2);
+
+			rc = device_add(&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;
+}
+
 static void fsi_slave_release(struct device *dev)
 {
 	struct fsi_slave *slave = to_fsi_slave(dev);
@@ -91,7 +218,8 @@ static int fsi_slave_init(struct fsi_master *master,
 		return rc;
 	}
 
-	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	[flat|nested] 24+ messages in thread

* [PATCH v3 11/18] drivers/fsi: Add device read/write/peek functions
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (9 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 10/18] drivers/fsi: scan slaves & register devices Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 12/18] drivers/fsi: Set up links for slave communication Christopher Bostic
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Jeremy Kerr, Chris Bostic

From: Jeremy Kerr <jk@ozlabs.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@us.ibm.com>

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 drivers/fsi/fsi-core.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fsi.h    |  6 ++++++
 2 files changed, 53 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index f7ef993..3119aa1 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -35,6 +35,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;
 
 static DEFINE_IDA(master_ida);
@@ -48,8 +50,46 @@ struct fsi_slave {
 
 #define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
 
+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)
+		return -EINVAL;
+
+	if (addr + size > dev->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)
+		return -EINVAL;
+
+	if (addr + size > dev->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);
@@ -81,6 +121,13 @@ static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
 			slave->id, addr, val, size);
 }
 
+static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
+			const void *val, size_t size)
+{
+	return slave->master->write(slave->master, slave->link,
+			slave->id, addr, val, 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 efa55ba..273945d 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;
-- 
1.8.2.2

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

* [PATCH v3 12/18] drivers/fsi: Set up links for slave communication
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (10 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 11/18] drivers/fsi: Add device read/write/peek functions Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 13/18] drivers/fsi: Set slave SMODE to init communication Christopher Bostic
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Chris Bostic, Jeremy Kerr

From: Chris Bostic <cbostic@us.ibm.com>

Enable each link and send a break command in preparation
for scanning each link for slaves.

Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
 drivers/fsi/fsi-core.c   | 38 ++++++++++++++++++++++++++++++++++++--
 drivers/fsi/fsi-master.h |  2 ++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 3119aa1..b2c9274 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -271,14 +271,48 @@ static int fsi_slave_init(struct fsi_master *master,
 
 /* FSI master support */
 
+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, slave_id;
+	int link, slave_id, 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 with:%d\n", link, rc);
+			continue;
+		}
+		rc = fsi_master_break(master, link);
+		if (rc) {
+			dev_dbg(master->dev,
+				"Break to link:%d failed with:%d\n", link, rc);
+			continue;
+		}
 
-	for (link = 0; link < master->n_links; link++)
 		for (slave_id = 0; slave_id < FSI_N_SLAVES; slave_id++)
 			fsi_slave_init(master, link, slave_id);
 
+	}
+
 	return 0;
 }
 
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index e75a810..94a0671 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -29,6 +29,8 @@ struct fsi_master {
 	int		(*write)(struct fsi_master *, int link,
 				uint8_t slave, uint32_t addr,
 				const void *val, size_t size);
+	int		(*send_break)(struct fsi_master *, int link);
+	int		(*link_enable)(struct fsi_master *, int link);
 };
 
 extern int fsi_master_register(struct fsi_master *master);
-- 
1.8.2.2

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

* [PATCH v3 13/18] drivers/fsi: Set slave SMODE to init communication
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (11 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 12/18] drivers/fsi: Set up links for slave communication Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 14/18] drivers/fsi: Remove all scanned devices during master unregister Christopher Bostic
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Chris Bostic, Jeremy Kerr

From: Chris Bostic <cbostic@us.ibm.com>

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

Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
---
 drivers/fsi/fsi-core.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 1 deletion(-)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index b2c9274..af7965f 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -36,6 +36,7 @@
 #define FSI_SLAVE_CONF_DATA_BITS	28
 
 #define FSI_PEEK_BASE			0x410
+#define	FSI_SLAVE_BASE			0x800
 
 static const int engine_page_size = 0x400;
 
@@ -55,8 +56,26 @@ static int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
 static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
 		const void *val, size_t size);
 
-/* FSI endpoint-device support */
+/*
+ * 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 */
 
+/* FSI endpoint-device support */
 int fsi_device_read(struct fsi_device *dev, uint32_t addr, void *val,
 		size_t size)
 {
@@ -114,6 +133,30 @@ static struct fsi_device *fsi_create_device(struct fsi_slave *slave)
 
 /* FSI slave support */
 
+/* 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 int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
 			void *val, size_t size)
 {
@@ -221,6 +264,22 @@ static void fsi_slave_release(struct device *dev)
 	kfree(slave);
 }
 
+static uint32_t set_smode_defaults(struct fsi_master *master)
+{
+	return FSI_SMODE_WSC | FSI_SMODE_ECRC
+		| fsi_smode_echodly(0xf) | fsi_smode_senddly(0xf)
+		| fsi_smode_lbcrr(1);
+}
+
+static int fsi_slave_set_smode(struct fsi_master *master, int link, int id)
+{
+	uint32_t smode = set_smode_defaults(master);
+
+	smode |= fsi_smode_sid(id);
+	return master->write(master, link, 3, FSI_SLAVE_BASE + FSI_SMODE,
+				&smode, sizeof(smode));
+}
+
 static int fsi_slave_init(struct fsi_master *master,
 		int link, uint8_t slave_id)
 {
@@ -229,6 +288,21 @@ static int fsi_slave_init(struct fsi_master *master,
 	int rc;
 	uint8_t crc;
 
+	/*
+	 * todo: Due to CFAM hardware issues related to BREAK commands we're
+	 * limited to only one CFAM per link.  Once issues are resolved this
+	 * restriction can be removed.
+	 */
+	if (slave_id > 0)
+		return 0;
+
+	rc = fsi_slave_set_smode(master, link, slave_id);
+	if (rc) {
+		dev_warn(master->dev, "can't set smode on slave:%02x:%02x %d\n",
+				link, slave_id, rc);
+		return -ENODEV;
+	}
+
 	rc = master->read(master, link, slave_id, 0, &chip_id, sizeof(chip_id));
 	if (rc) {
 		dev_warn(master->dev, "can't read slave %02x:%02x: %d\n",
@@ -293,6 +367,7 @@ static int fsi_master_break(struct fsi_master *master, int link)
 static int fsi_master_scan(struct fsi_master *master)
 {
 	int link, slave_id, rc;
+	uint32_t smode;
 
 	for (link = 0; link < master->n_links; link++) {
 		rc = fsi_master_link_enable(master, link);
@@ -308,6 +383,19 @@ static int fsi_master_scan(struct fsi_master *master)
 			continue;
 		}
 
+		/*
+		 * Verify can read slave at default ID location. If fails
+		 * there must be nothing on other end of link
+		 */
+		rc = master->read(master, link, 3, FSI_SLAVE_BASE + FSI_SMODE,
+				&smode, sizeof(smode));
+		if (rc) {
+			dev_dbg(master->dev,
+				"Read link:%d smode default id failed:%d\n",
+				link, rc);
+			continue;
+		}
+
 		for (slave_id = 0; slave_id < FSI_N_SLAVES; slave_id++)
 			fsi_slave_init(master, link, slave_id);
 
-- 
1.8.2.2

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

* [PATCH v3 14/18] drivers/fsi: Remove all scanned devices during master unregister
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (12 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 13/18] drivers/fsi: Set slave SMODE to init communication Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 15/18] drivers/fsi: Add FSI bus documentation Christopher Bostic
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Chris Bostic

From: Chris Bostic <cbostic@us.ibm.com>

Master will remove all previously scanned devices during an
unregister operation. This will be necessary should any master
attempt to register more than once.

Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 drivers/fsi/fsi-core.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index af7965f..28b82d1 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -428,12 +428,26 @@ int fsi_master_register(struct fsi_master *master)
 }
 EXPORT_SYMBOL_GPL(fsi_master_register);
 
+static int fsi_slave_device_remove(struct device *dev, void *data)
+{
+	put_device(dev);
+	return 0;
+}
+
+static int fsi_master_slave_remove(struct device *dev, void *data)
+{
+	device_for_each_child(dev, NULL, fsi_slave_device_remove);
+	device_unregister(dev);
+	return 0;
+}
+
 void fsi_master_unregister(struct fsi_master *master)
 {
 	if (!master || !master->dev)
 		return;
 
 	ida_simple_remove(&master_ida, master->idx);
+	device_for_each_child(master->dev, NULL, fsi_master_slave_remove);
 	put_device(master->dev);
 }
 EXPORT_SYMBOL_GPL(fsi_master_unregister);
-- 
1.8.2.2

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

* [PATCH v3 15/18] drivers/fsi: Add FSI bus documentation
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (13 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 14/18] drivers/fsi: Remove all scanned devices during master unregister Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-07 17:23   ` Rob Herring
  2017-02-01 16:53 ` [PATCH v3 16/18] drivers/fsi: Add documentation for GPIO based FSI master Christopher Bostic
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Chris Bostic

From: Chris Bostic <cbostic@us.ibm.com>

Add details on the basic functions of the FSI serial bus.

Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 Documentation/devicetree/bindings/fsi/fsi.txt | 54 +++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fsi/fsi.txt

diff --git a/Documentation/devicetree/bindings/fsi/fsi.txt b/Documentation/devicetree/bindings/fsi/fsi.txt
new file mode 100644
index 0000000..7fa2394
--- /dev/null
+++ b/Documentation/devicetree/bindings/fsi/fsi.txt
@@ -0,0 +1,54 @@
+FSI: Flexible Support processor Interface
+
+FSI is a two line serial bus capable of running at speeds up to 166 MHz.
+The lines consist of a clock responsible for synchronizing the target device
+(slave) with the master which is responsible for all transactions on the bus.
+The master owns the clock line and is the only side allowed to change its
+state. The second line, SDA, is a data line that conveys information to/from
+the slave who samples based on the clock line.  The data line is
+bi-directional.
+
+The master initiates communication by sending a command to the slave and
+depending on the type of command will allow the slave to control the bus
+to return requested data.  All commands are CRC protected.  The slave upon
+receipt of a command will determine if the CRC is correct and discard
+the data if noise has corrupted the line.  In the same manner the master
+will verify the CRC received from the slave.
+
+Types of commands:
+Read 32 bit:  Read a 32 bit word from a specified address on the slave.
+Read 16 bit:  Read a 16 bit 'half word' from a specified address on the slave.
+read 8 bit:   Read a byte from a specified address on the slave.
+Write 32,16,8 bit: Write to a specified address on the slave with the provided
+		data.
+BREAK:		Initialize the slave's logic to receive commands.
+TERM:		Terminate the slave's error lockout to resume communications
+		after an error on the bus is detected.
+D-POLL:		Poll the slave to determine when it is no longer buy processing
+		a previous command.
+I-POLL:		Interrupt signal check.  Master queries slave to see if any
+		interrupts are asserting.
+
+High fanout capability:
+FSI buses can be chained together in 'hub' configurations to expand the
+available communications channels and thus allow connetion to more slaves.
+
+
+Typical implementation
+
+ FSI master ----- slave with local FSI master (hub) ------- downstream slave
+
+
+Each two line combination of a clock and data line is collectively referred
+to as a 'FSI link'.   Depending on hardware the primary FSI master may support
+up to 64 links.  Hub FSI masters can support at most 8 links.  Total number
+of supported slaves can grow exponentially depending on how many hubs are
+placed in the path.  Presently only two hubs in the chain are allowed but
+in the future this may be expanded.
+
+The slave hardware logic responsible for decoding FSI master commands is
+contained in a CFAM (Common Field replaceable unit Access Macro).  Up to
+4 slaves or CFAMs can be connected on each FSI link.  CFAMs in addition
+to the slave logic (or engine) can contain other functions that allow access
+via FSI.  Common additional functionality includes I2C masters, GPIO
+controllers, UARTs, etc...
-- 
1.8.2.2

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

* [PATCH v3 16/18] drivers/fsi: Add documentation for GPIO based FSI master
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (14 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 15/18] drivers/fsi: Add FSI bus documentation Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-07 17:27   ` Rob Herring
  2017-02-01 16:53 ` [PATCH v3 17/18] drivers/fsi: Document FSI master sysfs files in ABI Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 18/18] drivers/fsi: Add GPIO based FSI master Christopher Bostic
  17 siblings, 1 reply; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Chris Bostic

From: Chris Bostic <cbostic@us.ibm.com>

Define the device tree bindings for the GPIO master type.

Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 .../devicetree/bindings/fsi/fsi-master-gpio.txt    | 71 ++++++++++++++++++++++
 1 file changed, 71 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..5d589bf
--- /dev/null
+++ b/Documentation/devicetree/bindings/fsi/fsi-master-gpio.txt
@@ -0,0 +1,71 @@
+Device-tree bindings for FSI master implemented with GPIO
+---------------------------------------------------------
+
+Typically a FSI master is defined in hardware with output control
+lines designated for Enable, Data, Clock, etc..  In the case of
+a 'GPIO FSI master', however, it may be the case that there is no
+such master defined in hardware and must be implemented in standard
+GPIO to interact with its slaves.  In this 'virtual' FSI master
+case the GPIO pins representing clk and data are directly
+connected to the slaves.
+
+The GPIO FSI master node
+-------------------------
+This node describes a FSI master implmented with GPIO.
+Required property:
+	compatible = "ibm,fsi-master-gpio"
+
+The standard FSI master node
+----------------------------
+This node describes a FSI master implmemented fully in hardware
+with dedicated input/output pins required for its function (i.e.
+not using generic GPIO pins).
+Required property:
+	compatible = "ibm,fsi-master"
+
+
+GPIO FSI master property/pin descriptions
+------------------------------------------
+clk -	The master controlled clock line that indicates to the
+	slave when to read in or send out new data - required.
+data -	The serial data line containing information to be sent or
+	received by the master.  This line is bi-directional.  During
+	command phase the master controls the line and when a response
+	is required the slave takes control - required.
+enable - Controls power state of data line - optional.
+trans - Voltage translator control. In some applications the data line
+	must have its signal levels altered by a translator. If this is
+	necessary then control of signal direction is managed via this
+	line - optional.
+mux -	Multiplexor control.  This activates/deactivates the data line
+	in cases where it is one of many possible selections via mux -
+	optional.
+
+Required properties:
+	- compatible = "ibm,fsi-master-gpio";
+	- clk-gpios;
+	- data-gpios;
+
+Optional properties:
+	- enable-gpios;
+	- trans-gpios;
+	- mux-gpios;
+
+Order of property activation:
+1. clk
+2. data
+3. trans
+4. enable
+5. mux
+
+
+Example:
+
+fsi-master {
+	compatible = "ibm,fsi-master-gpio", "ibm,fsi-master";
+	clk-gpios = <&gpio 0>, <&gpio 6>;
+	data-gpios = <&gpio 1>, <&gpio 7>;
+	enable-gpios = <&gpio 2>, <&gpio 8>;
+	trans-gpios = <&gpio 3>, <&gpio 9>;
+	mux-gpios = <&gpio 4>, <&gpio 10>;
+}
-- 
1.8.2.2

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

* [PATCH v3 17/18] drivers/fsi: Document FSI master sysfs files in ABI
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (15 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 16/18] drivers/fsi: Add documentation for GPIO based FSI master Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  2017-02-01 16:53 ` [PATCH v3 18/18] drivers/fsi: Add GPIO based FSI master Christopher Bostic
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Chris Bostic

From: Chris Bostic <cbostic@us.ibm.com>

Add info for sysfs scan file in Documentaiton ABI/testing

Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 Documentation/ABI/testing/sysfs-bus-fsi | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-fsi

diff --git a/Documentation/ABI/testing/sysfs-bus-fsi b/Documentation/ABI/testing/sysfs-bus-fsi
new file mode 100644
index 0000000..dfcbc1b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-fsi
@@ -0,0 +1,6 @@
+What:           /sys/bus/platform/devices/fsi-master/scan
+KernelVersion:  4.9
+Contact:        cbostic@us.ibm.com
+Description:
+                Initiates a FSI master scan for all connected
+                slave devices on its links.
-- 
1.8.2.2

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

* [PATCH v3 18/18] drivers/fsi: Add GPIO based FSI master
  2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
                   ` (16 preceding siblings ...)
  2017-02-01 16:53 ` [PATCH v3 17/18] drivers/fsi: Document FSI master sysfs files in ABI Christopher Bostic
@ 2017-02-01 16:53 ` Christopher Bostic
  17 siblings, 0 replies; 24+ messages in thread
From: Christopher Bostic @ 2017-02-01 16:53 UTC (permalink / raw)
  To: robh+dt, mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh
  Cc: Chris Bostic, Jeremy Kerr

From: Chris Bostic <cbostic@us.ibm.com>

Implement a FSI master using GPIO.  Will generate FSI protocol for
read and write commands to particular addresses.  Sends master command
and waits for and decodes a slave response.

Includes Jeremy Kerr's original GPIO master base commit.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
 drivers/fsi/Kconfig           |  11 +
 drivers/fsi/Makefile          |   1 +
 drivers/fsi/fsi-master-gpio.c | 530 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 542 insertions(+)
 create mode 100644 drivers/fsi/fsi-master-gpio.c

diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index 04c1a0e..9cf8345 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -9,4 +9,15 @@ config FSI
 	---help---
 	  FSI - the FRU Support Interface - is a simple bus for low-level
 	  access to POWER-based hardware.
+
+if FSI
+
+config FSI_MASTER_GPIO
+	tristate "GPIO-based FSI master"
+	depends on FSI && GPIOLIB
+	---help---
+	This option enables a FSI master driver using GPIO lines.
+
+endif
+
 endmenu
diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
index db0e5e7..ed28ac0 100644
--- a/drivers/fsi/Makefile
+++ b/drivers/fsi/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_FSI) += fsi-core.o
+obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o
diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
new file mode 100644
index 0000000..b549d0b
--- /dev/null
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -0,0 +1,530 @@
+/*
+ * FSI GPIO based master driver
+ *
+ * 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.
+ *
+ *
+ * A FSI master controller, using a simple GPIO bit-banging interface
+ */
+
+#include <linux/platform_device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/fsi.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/crc-fsi.h>
+
+#include "fsi-master.h"
+
+#define	FSI_GPIO_STD_DLY	1	/* Standard pin delay in nS */
+#define	FSI_ECHO_DELAY_CLOCKS	16	/* Number clocks for echo delay */
+#define	FSI_PRE_BREAK_CLOCKS	50	/* Number clocks to prep for break */
+#define	FSI_BREAK_CLOCKS	256	/* Number of clocks to issue break */
+#define	FSI_POST_BREAK_CLOCKS	16000	/* Number clocks to set up cfam */
+#define	FSI_INIT_CLOCKS		5000	/* Clock out any old data */
+#define	FSI_GPIO_STD_DELAY	10	/* Standard GPIO delay in nS */
+					/* todo: adjust down as low as */
+					/* possible or eliminate */
+#define	FSI_GPIO_CMD_DPOLL	0x000000000000002AULL
+#define	FSI_GPIO_CMD_DPOLL_SIZE	9
+#define	FSI_GPIO_DPOLL_CLOCKS	100      /* < 21 will cause slave to hang */
+#define	FSI_GPIO_CMD_DEFAULT	0x2000000000000000ULL
+#define	FSI_GPIO_CMD_WRITE	0
+#define	FSI_GPIO_CMD_READ	0x0400000000000000ULL
+#define	FSI_GPIO_CMD_SLAVE_MASK	0xC000000000000000ULL
+#define	FSI_GPIO_CMD_ADDR_SHIFT	37
+#define	FSI_GPIO_CMD_ADDR_MASK	0x001FFFFF
+#define	FSI_GPIO_CMD_SLV_SHIFT	62
+#define	FSI_GPIO_CMD_SIZE_16	0x0000001000000000ULL
+#define	FSI_GPIO_CMD_SIZE_32	0x0000003000000000ULL
+#define	FSI_GPIO_CMD_DT32_SHIFT	4
+#define	FSI_GPIO_CMD_DT16_SHIFT	20
+#define	FSI_GPIO_CMD_DT8_SHIFT	28
+#define	FSI_GPIO_CMD_DFLT_LEN	28
+#define	FSI_GPIO_CMD_CRC_SHIFT	60
+
+/* Bus errors */
+#define	FSI_GPIO_ERR_BUSY	1	/* Slave stuck in busy state */
+#define	FSI_GPIO_RESP_ERRA	2	/* Any (misc) Error */
+#define	FSI_GPIO_RESP_ERRC	3	/* Slave reports master CRC error */
+#define	FSI_GPIO_MTOE		4	/* Master time out error */
+#define	FSI_GPIO_CRC_INVAL	5	/* Master reports slave CRC error */
+
+/* Normal slave responses */
+#define	FSI_GPIO_RESP_BUSY	1
+#define	FSI_GPIO_RESP_ACK	0
+#define	FSI_GPIO_RESP_ACKD	4
+
+#define	FSI_GPIO_MAX_BUSY	100
+#define	FSI_GPIO_MTOE_COUNT	1000
+#define	FSI_GPIO_DRAIN_BITS	20
+#define	FSI_GPIO_CRC_SIZE	4
+#define	FSI_GPIO_MSG_ID_SIZE		2
+#define	FSI_GPIO_MSG_RESPID_SIZE	2
+#define	FSI_GPIO_PRIME_SLAVE_CLOCKS	100
+
+static DEFINE_SPINLOCK(fsi_gpio_cmd_lock);	/* lock around fsi commands */
+
+struct fsi_master_gpio {
+	struct fsi_master	master;
+	struct gpio_desc	*gpio_clk;
+	struct gpio_desc	*gpio_data;
+	struct gpio_desc	*gpio_trans;	/* Voltage translator */
+	struct gpio_desc	*gpio_enable;	/* FSI enable */
+	struct gpio_desc	*gpio_mux;	/* Mux control */
+};
+
+#define to_fsi_master_gpio(m) container_of(m, struct fsi_master_gpio, master)
+
+struct fsi_gpio_msg {
+	uint64_t	msg;
+	uint8_t		bits;
+};
+
+static void clock_toggle(struct fsi_master_gpio *master, int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		ndelay(FSI_GPIO_STD_DLY);
+		gpiod_set_value(master->gpio_clk, 0);
+		ndelay(FSI_GPIO_STD_DLY);
+		gpiod_set_value(master->gpio_clk, 1);
+	}
+}
+
+static int sda_in(struct fsi_master_gpio *master)
+{
+	int in;
+
+	ndelay(FSI_GPIO_STD_DLY);
+	in = gpiod_get_value(master->gpio_data);
+	return in ? 1 : 0;
+}
+
+static void sda_out(struct fsi_master_gpio *master, int value)
+{
+	gpiod_set_value(master->gpio_data, value);
+}
+
+static void set_sda_input(struct fsi_master_gpio *master)
+{
+	gpiod_direction_input(master->gpio_data);
+	if (master->gpio_trans)
+		gpiod_set_value(master->gpio_trans, 0);
+}
+
+static void set_sda_output(struct fsi_master_gpio *master, int value)
+{
+	if (master->gpio_trans)
+		gpiod_set_value(master->gpio_trans, 1);
+	gpiod_direction_output(master->gpio_data, value);
+}
+
+static void serial_in(struct fsi_master_gpio *master, struct fsi_gpio_msg *cmd,
+			uint8_t num_bits)
+{
+	uint8_t bit;
+	uint64_t msg = 0;
+	uint8_t in_bit = 0;
+
+	set_sda_input(master);
+
+	for (bit = 0; bit < num_bits; bit++) {
+		clock_toggle(master, 1);
+		in_bit = sda_in(master);
+		msg <<= 1;
+		msg |= ~in_bit & 0x1;	/* Data is negative active */
+	}
+	cmd->bits = num_bits;
+	cmd->msg = msg;
+}
+
+static void serial_out(struct fsi_master_gpio *master,
+			const struct fsi_gpio_msg *cmd)
+{
+	uint8_t bit;
+	uint64_t msg = ~cmd->msg;	/* Data is negative active */
+	uint64_t sda_mask = 0x1ULL << (cmd->bits - 1);
+	uint64_t last_bit = ~0;
+	int next_bit;
+
+	if (!cmd->bits) {
+		dev_warn(master->master.dev, "trying to output 0 bits\n");
+		return;
+	}
+	set_sda_output(master, 0);
+
+	/* Send the start bit */
+	sda_out(master, 0);
+	clock_toggle(master, 1);
+
+	/* Send the message */
+	for (bit = 0; bit < cmd->bits; bit++) {
+		next_bit = (msg & sda_mask) >> (cmd->bits - 1);
+		if (last_bit ^ next_bit) {
+			sda_out(master, next_bit);
+			last_bit = next_bit;
+		}
+		clock_toggle(master, 1);
+		msg <<= 1;
+	}
+}
+
+/*
+ * Clock out some 0's after every message to ride out line reflections
+ */
+static void echo_delay(struct fsi_master_gpio *master)
+{
+	set_sda_output(master, 1);
+	clock_toggle(master, FSI_ECHO_DELAY_CLOCKS);
+}
+
+/*
+ * Used in bus error cases only.  Clears out any remaining data the slave
+ * is attempting to send
+ */
+static void drain_response(struct fsi_master_gpio *master)
+{
+	struct fsi_gpio_msg msg;
+
+	serial_in(master, &msg, FSI_GPIO_DRAIN_BITS);
+}
+
+/*
+ * Store information on master errors so handler can detect and clean
+ * up the bus
+ */
+static void fsi_master_gpio_error(struct fsi_master_gpio *master, int error)
+{
+
+}
+
+static int poll_for_response(struct fsi_master_gpio *master, uint8_t expected,
+			uint8_t size, void *data)
+{
+	int busy_count = 0, i;
+	struct fsi_gpio_msg response, cmd;
+	int bits_remaining = 0, bit_count, response_id, id;
+	uint64_t resp = 0;
+	uint8_t bits_received = FSI_GPIO_MSG_ID_SIZE +
+				FSI_GPIO_MSG_RESPID_SIZE;
+	uint8_t crc_in;
+
+	do {
+		for (i = 0; i < FSI_GPIO_MTOE_COUNT; i++) {
+			serial_in(master, &response, 1);
+			if (response.msg)
+				break;
+		}
+		if (i >= FSI_GPIO_MTOE_COUNT) {
+			dev_dbg(master->master.dev,
+				"Master time out waiting for response\n");
+			drain_response(master);
+			fsi_master_gpio_error(master, FSI_GPIO_MTOE);
+			return -EIO;
+		}
+
+		/* Response received */
+		bit_count = FSI_GPIO_MSG_ID_SIZE + FSI_GPIO_MSG_RESPID_SIZE;
+		serial_in(master, &response, bit_count);
+
+		response_id = response.msg & 0x3;
+		id = (response.msg >> FSI_GPIO_MSG_RESPID_SIZE) & 0x3;
+		dev_dbg(master->master.dev, "id:%d resp:%d\n", id, response_id);
+
+		resp = response.msg;
+
+		switch (response_id) {
+		case FSI_GPIO_RESP_ACK:
+			if (expected == FSI_GPIO_RESP_ACKD)
+				bits_remaining = 8 * size;
+			break;
+
+		case FSI_GPIO_RESP_BUSY:
+			/*
+			 * Its necessary to clock slave before issuing
+			 * d-poll, not indicated in the hardware protocol
+			 * spec. < 20 clocks causes slave to hang, 21 ok.
+			 */
+			set_sda_output(master, 1);
+			clock_toggle(master, FSI_GPIO_DPOLL_CLOCKS);
+			cmd.msg = FSI_GPIO_CMD_DPOLL;
+			cmd.bits = FSI_GPIO_CMD_DPOLL_SIZE;
+			serial_out(master, &cmd);
+			echo_delay(master);
+			continue;
+
+		case FSI_GPIO_RESP_ERRA:
+		case FSI_GPIO_RESP_ERRC:
+			dev_dbg(master->master.dev, "ERR received: %d\n",
+				(int)response.msg);
+			/*
+			 * todo: Verify crc from slave and in general
+			 * only act on any response if crc is correct
+			 */
+			clock_toggle(master, FSI_GPIO_CRC_SIZE);
+			fsi_master_gpio_error(master, response.msg);
+			return -EIO;
+		}
+
+		/* Read in the data field if applicable */
+		if (bits_remaining) {
+			serial_in(master, &response, bits_remaining);
+			resp <<= bits_remaining;
+			resp |= response.msg;
+			bits_received += bits_remaining;
+			*((uint32_t *)data) = response.msg;
+		}
+
+		crc_in = crc_fsi(0, resp | (0x1ULL << bits_received),
+					bits_received + 1);
+
+		/* Read in the crc and check it */
+		serial_in(master, &response, FSI_GPIO_CRC_SIZE);
+		if (crc_in != response.msg) {
+			dev_dbg(master->master.dev, "ERR response CRC\n");
+			fsi_master_gpio_error(master, FSI_GPIO_CRC_INVAL);
+			return -EIO;
+		}
+		/* Clock the slave enough to be ready for next operation */
+		clock_toggle(master, FSI_GPIO_PRIME_SLAVE_CLOCKS);
+		return 0;
+
+	} while (busy_count++ < FSI_GPIO_MAX_BUSY);
+
+	dev_dbg(master->master.dev, "ERR slave is stuck in busy state\n");
+	fsi_master_gpio_error(master, FSI_GPIO_ERR_BUSY);
+
+	return -EIO;
+}
+
+static void build_abs_ar_command(struct fsi_gpio_msg *cmd, uint64_t mode,
+		uint8_t slave, uint32_t addr, size_t size,
+		const void *data)
+{
+	uint8_t crc;
+
+	cmd->bits = FSI_GPIO_CMD_DFLT_LEN;
+	cmd->msg = FSI_GPIO_CMD_DEFAULT;
+	cmd->msg |= mode;
+	cmd->msg &= ~FSI_GPIO_CMD_SLAVE_MASK;
+	cmd->msg |= (((uint64_t)slave) << FSI_GPIO_CMD_SLV_SHIFT);
+	addr &= FSI_GPIO_CMD_ADDR_MASK;
+	cmd->msg |= (((uint64_t)addr) << FSI_GPIO_CMD_ADDR_SHIFT);
+	if (size == sizeof(uint8_t)) {
+		if (data) {
+			uint8_t cmd_data = *((uint8_t *)data);
+
+			cmd->msg |=
+				((uint64_t)cmd_data) << FSI_GPIO_CMD_DT8_SHIFT;
+		}
+	} else if (size == sizeof(uint16_t)) {
+		cmd->msg |= FSI_GPIO_CMD_SIZE_16;
+		if (data) {
+			uint16_t cmd_data;
+
+			memcpy(&cmd_data, data, size);
+			cmd->msg |=
+				((uint64_t)cmd_data) << FSI_GPIO_CMD_DT16_SHIFT;
+		}
+	} else {
+		cmd->msg |= FSI_GPIO_CMD_SIZE_32;
+		if (data) {
+			uint32_t cmd_data;
+
+			memcpy(&cmd_data, data, size);
+			cmd->msg |=
+				((uint64_t)cmd_data) << FSI_GPIO_CMD_DT32_SHIFT;
+		}
+	}
+
+	if (mode == FSI_GPIO_CMD_WRITE)
+		cmd->bits += (8 * size);
+
+	/* Include start bit */
+	crc = crc_fsi(0,
+			(cmd->msg >> (64 - cmd->bits)) | (0x1ULL << cmd->bits),
+			cmd->bits + 1);
+	cmd->msg |= ((uint64_t)crc) << (FSI_GPIO_CMD_CRC_SHIFT - cmd->bits);
+	cmd->bits += FSI_GPIO_CRC_SIZE;
+
+	/* Right align message */
+	cmd->msg >>= (64 - cmd->bits);
+}
+
+static int fsi_master_gpio_read(struct fsi_master *_master, int link,
+		uint8_t slave, uint32_t addr, void *val, size_t size)
+{
+	struct fsi_master_gpio *master = to_fsi_master_gpio(_master);
+	struct fsi_gpio_msg cmd;
+	int rc;
+	unsigned long flags;
+
+	if (link != 0)
+		return -ENODEV;
+
+	build_abs_ar_command(&cmd, FSI_GPIO_CMD_READ, slave, addr, size, NULL);
+
+	spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
+	serial_out(master, &cmd);
+	echo_delay(master);
+	rc = poll_for_response(master, FSI_GPIO_RESP_ACKD, size, val);
+	spin_unlock_irqrestore(&fsi_gpio_cmd_lock, flags);
+
+	return rc;
+}
+
+static int fsi_master_gpio_write(struct fsi_master *_master, int link,
+		uint8_t slave, uint32_t addr, const void *val, size_t size)
+{
+	struct fsi_master_gpio *master = to_fsi_master_gpio(_master);
+	struct fsi_gpio_msg cmd;
+	int rc;
+	unsigned long flags;
+
+	if (link != 0)
+		return -ENODEV;
+
+	build_abs_ar_command(&cmd, FSI_GPIO_CMD_WRITE, slave, addr, size, val);
+
+	spin_lock_irqsave(&fsi_gpio_cmd_lock, flags);
+	serial_out(master, &cmd);
+	echo_delay(master);
+	rc = poll_for_response(master, FSI_GPIO_RESP_ACK, size, NULL);
+	spin_unlock_irqrestore(&fsi_gpio_cmd_lock, flags);
+
+	return rc;
+}
+
+/*
+ * Issue a break command on link
+ */
+static int fsi_master_gpio_break(struct fsi_master *_master, int link)
+{
+	struct fsi_master_gpio *master = to_fsi_master_gpio(_master);
+
+	if (link != 0)
+		return -ENODEV;
+
+	set_sda_output(master, 1);
+	clock_toggle(master, FSI_PRE_BREAK_CLOCKS);
+	sda_out(master, 0);
+	clock_toggle(master, FSI_BREAK_CLOCKS);
+	echo_delay(master);
+	sda_out(master, 1);
+	clock_toggle(master, FSI_POST_BREAK_CLOCKS);
+
+	/* Wait for logic reset to take effect */
+	udelay(200);
+
+	return 0;
+}
+
+static int fsi_master_gpio_link_enable(struct fsi_master *_master, int link)
+{
+	struct fsi_master_gpio *master = to_fsi_master_gpio(_master);
+
+	if (link != 0)
+		return -ENODEV;
+	if (master->gpio_enable)
+		gpiod_set_value(master->gpio_enable, 1);
+
+	return 0;
+}
+
+static int fsi_master_gpio_probe(struct platform_device *pdev)
+{
+	struct fsi_master_gpio *master;
+
+	master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL);
+	if (!master)
+		return -ENOMEM;
+
+	master->master.dev = &pdev->dev;
+
+	master->gpio_clk = devm_gpiod_get(&pdev->dev, "clock", GPIOD_OUT_HIGH);
+	if (IS_ERR(master->gpio_clk)) {
+		dev_dbg(&pdev->dev, "probe: failed to get clock pin\n");
+		return PTR_ERR(master->gpio_clk);
+	}
+
+	master->gpio_data = devm_gpiod_get(&pdev->dev, "data", GPIOD_OUT_HIGH);
+	if (IS_ERR(master->gpio_data)) {
+		dev_dbg(&pdev->dev, "probe: failed to get data pin\n");
+		return PTR_ERR(master->gpio_data);
+	}
+
+	/* Optional pins */
+
+	master->gpio_trans = devm_gpiod_get_optional(&pdev->dev, "trans",
+							GPIOD_OUT_HIGH);
+	if (IS_ERR(master->gpio_trans))
+		dev_dbg(&pdev->dev, "probe: failed to get trans pin\n");
+
+	master->gpio_enable = devm_gpiod_get_optional(&pdev->dev, "enable",
+							GPIOD_OUT_HIGH);
+	if (IS_ERR(master->gpio_enable))
+		dev_dbg(&pdev->dev, "probe: failed to get enable pin\n");
+
+	master->gpio_mux = devm_gpiod_get_optional(&pdev->dev, "mux",
+							GPIOD_OUT_HIGH);
+	if (IS_ERR(master->gpio_mux))
+		dev_dbg(&pdev->dev, "probe: failed to get mux pin\n");
+
+	/* todo: evaluate if clocks can be reduced */
+	clock_toggle(master, FSI_INIT_CLOCKS);
+
+	master->master.n_links = 1;
+	master->master.read = fsi_master_gpio_read;
+	master->master.write = fsi_master_gpio_write;
+	master->master.send_break = fsi_master_gpio_break;
+	master->master.link_enable = fsi_master_gpio_link_enable;
+	return fsi_master_register(&master->master);
+}
+
+static int fsi_master_gpio_remove(struct platform_device *pdev)
+{
+	struct fsi_master_gpio *master = platform_get_drvdata(pdev);
+
+	devm_gpiod_put(&pdev->dev, master->gpio_clk);
+	devm_gpiod_put(&pdev->dev, master->gpio_data);
+	if (master->gpio_trans)
+		devm_gpiod_put(&pdev->dev, master->gpio_trans);
+	if (master->gpio_enable)
+		devm_gpiod_put(&pdev->dev, master->gpio_enable);
+	if (master->gpio_mux)
+		devm_gpiod_put(&pdev->dev, master->gpio_mux);
+	fsi_master_unregister(&master->master);
+
+	return 0;
+}
+
+static const struct of_device_id fsi_master_gpio_match[] = {
+	{ .compatible = "ibm,fsi-master-gpio" },
+	{ },
+};
+
+static struct platform_driver fsi_master_gpio_driver = {
+	.driver = {
+		.name		= "fsi-master-gpio",
+		.of_match_table	= fsi_master_gpio_match,
+	},
+	.probe	= fsi_master_gpio_probe,
+	.remove = fsi_master_gpio_remove,
+};
+
+module_platform_driver(fsi_master_gpio_driver);
+MODULE_LICENSE("GPL");
-- 
1.8.2.2

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

* Re: [PATCH v3 15/18] drivers/fsi: Add FSI bus documentation
  2017-02-01 16:53 ` [PATCH v3 15/18] drivers/fsi: Add FSI bus documentation Christopher Bostic
@ 2017-02-07 17:23   ` Rob Herring
  0 siblings, 0 replies; 24+ messages in thread
From: Rob Herring @ 2017-02-07 17:23 UTC (permalink / raw)
  To: Christopher Bostic
  Cc: mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh, Chris Bostic

On Wed, Feb 01, 2017 at 10:53:55AM -0600, Christopher Bostic wrote:
> From: Chris Bostic <cbostic@us.ibm.com>
> 
> Add details on the basic functions of the FSI serial bus.
> 
> Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
> ---
>  Documentation/devicetree/bindings/fsi/fsi.txt | 54 +++++++++++++++++++++++++++
>  1 file changed, 54 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/fsi/fsi.txt
> 
> diff --git a/Documentation/devicetree/bindings/fsi/fsi.txt b/Documentation/devicetree/bindings/fsi/fsi.txt
> new file mode 100644
> index 0000000..7fa2394
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/fsi/fsi.txt
> @@ -0,0 +1,54 @@
> +FSI: Flexible Support processor Interface
> +
> +FSI is a two line serial bus capable of running at speeds up to 166 MHz.
> +The lines consist of a clock responsible for synchronizing the target device
> +(slave) with the master which is responsible for all transactions on the bus.
> +The master owns the clock line and is the only side allowed to change its
> +state. The second line, SDA, is a data line that conveys information to/from
> +the slave who samples based on the clock line.  The data line is
> +bi-directional.
> +
> +The master initiates communication by sending a command to the slave and
> +depending on the type of command will allow the slave to control the bus
> +to return requested data.  All commands are CRC protected.  The slave upon
> +receipt of a command will determine if the CRC is correct and discard
> +the data if noise has corrupted the line.  In the same manner the master
> +will verify the CRC received from the slave.
> +
> +Types of commands:
> +Read 32 bit:  Read a 32 bit word from a specified address on the slave.
> +Read 16 bit:  Read a 16 bit 'half word' from a specified address on the slave.
> +read 8 bit:   Read a byte from a specified address on the slave.
> +Write 32,16,8 bit: Write to a specified address on the slave with the provided
> +		data.
> +BREAK:		Initialize the slave's logic to receive commands.
> +TERM:		Terminate the slave's error lockout to resume communications
> +		after an error on the bus is detected.
> +D-POLL:		Poll the slave to determine when it is no longer buy processing
> +		a previous command.
> +I-POLL:		Interrupt signal check.  Master queries slave to see if any
> +		interrupts are asserting.
> +
> +High fanout capability:
> +FSI buses can be chained together in 'hub' configurations to expand the
> +available communications channels and thus allow connetion to more slaves.
> +
> +
> +Typical implementation
> +
> + FSI master ----- slave with local FSI master (hub) ------- downstream slave
> +
> +
> +Each two line combination of a clock and data line is collectively referred
> +to as a 'FSI link'.   Depending on hardware the primary FSI master may support
> +up to 64 links.  Hub FSI masters can support at most 8 links.  Total number
> +of supported slaves can grow exponentially depending on how many hubs are
> +placed in the path.  Presently only two hubs in the chain are allowed but
> +in the future this may be expanded.

This document now isn't really more that a description of FSI. You need 
to define how the above bus structure gets reflected in DT. I assume the 
root is the FSI master, each child node is a link, a child can be a hub 
with its children being more links. What is the format of reg property 
is another thing to define.

> +
> +The slave hardware logic responsible for decoding FSI master commands is
> +contained in a CFAM (Common Field replaceable unit Access Macro).  Up to
> +4 slaves or CFAMs can be connected on each FSI link.  CFAMs in addition
> +to the slave logic (or engine) can contain other functions that allow access
> +via FSI.  Common additional functionality includes I2C masters, GPIO
> +controllers, UARTs, etc...
> -- 
> 1.8.2.2
> 

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

* Re: [PATCH v3 16/18] drivers/fsi: Add documentation for GPIO based FSI master
  2017-02-01 16:53 ` [PATCH v3 16/18] drivers/fsi: Add documentation for GPIO based FSI master Christopher Bostic
@ 2017-02-07 17:27   ` Rob Herring
  0 siblings, 0 replies; 24+ messages in thread
From: Rob Herring @ 2017-02-07 17:27 UTC (permalink / raw)
  To: Christopher Bostic
  Cc: mark.rutland, linux, gregkh, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh, Chris Bostic

On Wed, Feb 01, 2017 at 10:53:56AM -0600, Christopher Bostic wrote:
> From: Chris Bostic <cbostic@us.ibm.com>
> 
> Define the device tree bindings for the GPIO master type.
> 
> Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
> ---
>  .../devicetree/bindings/fsi/fsi-master-gpio.txt    | 71 ++++++++++++++++++++++
>  1 file changed, 71 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..5d589bf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/fsi/fsi-master-gpio.txt
> @@ -0,0 +1,71 @@
> +Device-tree bindings for FSI master implemented with GPIO
> +---------------------------------------------------------
> +
> +Typically a FSI master is defined in hardware with output control
> +lines designated for Enable, Data, Clock, etc..  In the case of
> +a 'GPIO FSI master', however, it may be the case that there is no
> +such master defined in hardware and must be implemented in standard
> +GPIO to interact with its slaves.  In this 'virtual' FSI master
> +case the GPIO pins representing clk and data are directly
> +connected to the slaves.
> +
> +The GPIO FSI master node
> +-------------------------
> +This node describes a FSI master implmented with GPIO.
> +Required property:
> +	compatible = "ibm,fsi-master-gpio"
> +
> +The standard FSI master node
> +----------------------------
> +This node describes a FSI master implmemented fully in hardware
> +with dedicated input/output pins required for its function (i.e.
> +not using generic GPIO pins).
> +Required property:
> +	compatible = "ibm,fsi-master"

This section still needs to be a separate doc. And ibm,fsi-master is too 
generic.

> +
> +
> +GPIO FSI master property/pin descriptions
> +------------------------------------------
> +clk -	The master controlled clock line that indicates to the
> +	slave when to read in or send out new data - required.

Just put the definitions with the properties (i.e. clk-gpios).

> +data -	The serial data line containing information to be sent or
> +	received by the master.  This line is bi-directional.  During
> +	command phase the master controls the line and when a response
> +	is required the slave takes control - required.
> +enable - Controls power state of data line - optional.
> +trans - Voltage translator control. In some applications the data line
> +	must have its signal levels altered by a translator. If this is
> +	necessary then control of signal direction is managed via this
> +	line - optional.
> +mux -	Multiplexor control.  This activates/deactivates the data line
> +	in cases where it is one of many possible selections via mux -
> +	optional.
> +
> +Required properties:
> +	- compatible = "ibm,fsi-master-gpio";
> +	- clk-gpios;
> +	- data-gpios;
> +
> +Optional properties:
> +	- enable-gpios;
> +	- trans-gpios;
> +	- mux-gpios;
> +
> +Order of property activation:
> +1. clk
> +2. data
> +3. trans
> +4. enable
> +5. mux
> +
> +
> +Example:
> +
> +fsi-master {
> +	compatible = "ibm,fsi-master-gpio", "ibm,fsi-master";

Aren't these 2 mutually exclusive?

> +	clk-gpios = <&gpio 0>, <&gpio 6>;
> +	data-gpios = <&gpio 1>, <&gpio 7>;
> +	enable-gpios = <&gpio 2>, <&gpio 8>;
> +	trans-gpios = <&gpio 3>, <&gpio 9>;
> +	mux-gpios = <&gpio 4>, <&gpio 10>;
> +}
> -- 
> 1.8.2.2
> 

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

* Re: [PATCH v3 04/18] drivers/fsi: Add fsi master definition
  2017-02-01 16:53 ` [PATCH v3 04/18] drivers/fsi: Add fsi master definition Christopher Bostic
@ 2017-02-10 14:21   ` Greg KH
  0 siblings, 0 replies; 24+ messages in thread
From: Greg KH @ 2017-02-10 14:21 UTC (permalink / raw)
  To: Christopher Bostic
  Cc: robh+dt, mark.rutland, linux, mturquette, geert+renesas,
	devicetree, linux-arm-kernel, joel, linux-kernel, andrew,
	alistair, benh, Jeremy Kerr, Chris Bostic

On Wed, Feb 01, 2017 at 10:53:44AM -0600, Christopher Bostic wrote:
> From: Jeremy Kerr <jk@ozlabs.org>
> 
> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
> Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
> ---
>  drivers/fsi/fsi-core.c   | 28 ++++++++++++++++++++++++++++
>  drivers/fsi/fsi-master.h | 37 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 65 insertions(+)
>  create mode 100644 drivers/fsi/fsi-master.h

I can't take patches without any changelog text, so please fix up and
resend the remaining patches in the series.

thanks,

greg k-h

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

* Re: [PATCH v3 01/18] drivers/fsi: Add empty fsi bus definitions
  2017-02-01 16:53 ` [PATCH v3 01/18] drivers/fsi: Add empty fsi bus definitions Christopher Bostic
@ 2017-02-23 10:53   ` Geert Uytterhoeven
  2017-02-23 14:24     ` Jeremy Kerr
  0 siblings, 1 reply; 24+ messages in thread
From: Geert Uytterhoeven @ 2017-02-23 10:53 UTC (permalink / raw)
  To: Christopher Bostic, Jeremy Kerr
  Cc: Rob Herring, Mark Rutland, Russell King, Greg KH,
	Michael Turquette, Geert Uytterhoeven, devicetree,
	linux-arm-kernel, joel, linux-kernel, andrew, Alistair Popple,
	Benjamin Herrenschmidt, Chris Bostic

Hi Chris, Jeremy,

On Wed, Feb 1, 2017 at 5:53 PM, Christopher Bostic
<cbostic@linux.vnet.ibm.com> wrote:
> From: Jeremy Kerr <jk@ozlabs.org>
>
> This change adds the initial (empty) fsi bus definition, and introduces
> drivers/fsi/.
>
> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
> Signed-off-by: Chris Bostic <cbostic@us.ibm.com>

> --- /dev/null
> +++ b/drivers/fsi/Kconfig
> @@ -0,0 +1,12 @@
> +#
> +# FSI subsystem
> +#
> +
> +menu "FSI support"
> +
> +config FSI
> +       tristate "FSI support"

I guess this should depend on some POWER symbol || COMPILE_TEST?

> +       ---help---
> +         FSI - the FRU Support Interface - is a simple bus for low-level
> +         access to POWER-based hardware.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v3 01/18] drivers/fsi: Add empty fsi bus definitions
  2017-02-23 10:53   ` Geert Uytterhoeven
@ 2017-02-23 14:24     ` Jeremy Kerr
  0 siblings, 0 replies; 24+ messages in thread
From: Jeremy Kerr @ 2017-02-23 14:24 UTC (permalink / raw)
  To: Geert Uytterhoeven, Christopher Bostic
  Cc: Rob Herring, Mark Rutland, Russell King, Greg KH,
	Michael Turquette, Geert Uytterhoeven, devicetree,
	linux-arm-kernel, joel, linux-kernel, andrew, Alistair Popple,
	Benjamin Herrenschmidt, Chris Bostic

Hi Geert,

>> --- /dev/null
>> +++ b/drivers/fsi/Kconfig
>> @@ -0,0 +1,12 @@
>> +#
>> +# FSI subsystem
>> +#
>> +
>> +menu "FSI support"
>> +
>> +config FSI
>> +       tristate "FSI support"
> 
> I guess this should depend on some POWER symbol || COMPILE_TEST?

No, this is pretty hardware-independent - all it requires on the HW side
is two GPIOs.

Although the FSI slave devices are typically only present on POWER
systems, they can be driven from anything, with currently
implementations being on ARM and 32-bit powerpc.

Cheers,


Jeremy

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

end of thread, other threads:[~2017-02-23 14:24 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-01 16:53 [PATCH v3 00/18] FSI device driver introduction Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 01/18] drivers/fsi: Add empty fsi bus definitions Christopher Bostic
2017-02-23 10:53   ` Geert Uytterhoeven
2017-02-23 14:24     ` Jeremy Kerr
2017-02-01 16:53 ` [PATCH v3 02/18] drivers/fsi: Add device & driver definitions Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 03/18] drivers/fsi: add driver to device matches Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 04/18] drivers/fsi: Add fsi master definition Christopher Bostic
2017-02-10 14:21   ` Greg KH
2017-02-01 16:53 ` [PATCH v3 05/18] drivers/fsi: Add slave definition Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 06/18] drivers/fsi: Add empty master scan Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 07/18] drivers/fsi: Add FSI crc calculators to library Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 08/18] drivers/fsi: Kick off master scan via sysfs Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 09/18] drivers/fsi: Implement slave initialisation Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 10/18] drivers/fsi: scan slaves & register devices Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 11/18] drivers/fsi: Add device read/write/peek functions Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 12/18] drivers/fsi: Set up links for slave communication Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 13/18] drivers/fsi: Set slave SMODE to init communication Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 14/18] drivers/fsi: Remove all scanned devices during master unregister Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 15/18] drivers/fsi: Add FSI bus documentation Christopher Bostic
2017-02-07 17:23   ` Rob Herring
2017-02-01 16:53 ` [PATCH v3 16/18] drivers/fsi: Add documentation for GPIO based FSI master Christopher Bostic
2017-02-07 17:27   ` Rob Herring
2017-02-01 16:53 ` [PATCH v3 17/18] drivers/fsi: Document FSI master sysfs files in ABI Christopher Bostic
2017-02-01 16:53 ` [PATCH v3 18/18] drivers/fsi: Add GPIO based FSI master Christopher Bostic

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).