* [PATCH 02/16] drivers/fsi: Add device & driver definitions
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
sre-DgEjT+Ai2ygdnm+yROfE0A, mturquette-rdvid1DuHRBWk0Htik3J/w,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
alistair-Y4h6yKqj69EXC2x5gXVKYQ,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Chris Bostic
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Add structs for fsi devices & drivers, and struct device conversion
functions.
Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 03/16] drivers/fsi: add driver to device matches
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: andrew, alistair, linux-kernel, Chris Bostic, Jeremy Kerr, benh,
joel
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic@gmail.com>
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
* [PATCH 05/16] drivers/fsi: Add fake master driver
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
Chris Bostic
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic@gmail.com>
From: Jeremy Kerr <jk@ozlabs.org>
For debugging, add a fake master driver, that only supports reads,
returning a fixed set of data.
Includes changes 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/Kconfig | 10 +++++
drivers/fsi/Makefile | 1 +
drivers/fsi/fsi-master-fake.c | 95 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 106 insertions(+)
create mode 100644 drivers/fsi/fsi-master-fake.c
diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index 04c1a0e..f065dbe 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -9,4 +9,14 @@ 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_FAKE
+ tristate "Fake FSI master"
+ depends on FSI
+ ---help---
+ This option enables a fake FSI master driver for debugging.
+endif
+
endmenu
diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
index db0e5e7..847c00c 100644
--- a/drivers/fsi/Makefile
+++ b/drivers/fsi/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_FSI) += fsi-core.o
+obj-$(CONFIG_FSI_MASTER_FAKE) += fsi-master-fake.o
diff --git a/drivers/fsi/fsi-master-fake.c b/drivers/fsi/fsi-master-fake.c
new file mode 100644
index 0000000..b42fe5b
--- /dev/null
+++ b/drivers/fsi/fsi-master-fake.c
@@ -0,0 +1,95 @@
+/*
+ * Fake FSI master driver for FSI development
+ *
+ * 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/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#include "fsi-master.h"
+
+static const uint8_t data[] = {
+ 0xc0, 0x02, 0x08, 0x03, /* chip id */
+ 0x80, 0x01, 0x11, 0x00, /* peek */
+ 0x80, 0x01, 0x20, 0x3e, /* slave */
+ 0x00, 0x01, 0x10, 0xa5, /* i2c */
+};
+
+
+static int fsi_master_fake_read(struct fsi_master *_master, int link,
+ uint8_t slave, uint32_t addr, void *val, size_t size)
+{
+ if (link != 0)
+ return -ENODEV;
+
+ if (addr + size > sizeof(data))
+ memset(val, 0, size);
+ else
+ memcpy(val, data + addr, size);
+
+ return 0;
+}
+
+static int fsi_master_fake_write(struct fsi_master *_master, int link,
+ uint8_t slave, uint32_t addr, const void *val, size_t size)
+{
+ if (link != 0)
+ return -ENODEV;
+
+ return -EACCES;
+}
+
+static int fsi_master_fake_probe(struct platform_device *pdev)
+{
+ struct fsi_master *master;
+
+ master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL);
+ if (!master)
+ return -ENOMEM;
+
+ master->dev = &pdev->dev;
+ master->n_links = 1;
+ master->read = fsi_master_fake_read;
+ master->write = fsi_master_fake_write;
+
+ return fsi_master_register(master);
+}
+
+static const struct of_device_id fsi_master_fake_match[] = {
+ { .compatible = "ibm,fsi-master-fake" },
+ { },
+};
+
+static struct platform_driver fsi_master_fake_driver = {
+ .driver = {
+ .name = "fsi-master-fake",
+ .of_match_table = fsi_master_fake_match,
+ },
+ .probe = fsi_master_fake_probe,
+};
+
+static int __init fsi_master_fake_init(void)
+{
+ struct device_node *np;
+
+ platform_driver_register(&fsi_master_fake_driver);
+
+ for_each_compatible_node(np, NULL, "ibm,fsi-master-fake")
+ of_platform_device_create(np, NULL, NULL);
+
+ return 0;
+}
+
+module_init(fsi_master_fake_init);
--
1.8.2.2
^ permalink raw reply related
* [PATCH 06/16] drivers/fsi: Add slave definition
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
Chris Bostic
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic@gmail.com>
From: Jeremy Kerr <jk@ozlabs.org>
Add the initial fsi slave device, which is private to the core code.
This will be a child of the master, and parent to endpoint devices.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@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 ce9428d..60a6d91 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -21,6 +21,15 @@
static atomic_t master_idx = ATOMIC_INIT(-1);
+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
* [PATCH 07/16] drivers/fsi: Add empty master scan
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
Chris Bostic
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic@gmail.com>
From: Jeremy Kerr <jk@ozlabs.org>
When a new fsi master is added, we will need to scan its links, and
slaves attached to those links. This change introduces a little shell to
iterate the links, which we will populate with the actual slave scan in
a later change.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@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 60a6d91..ceaf536 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -19,6 +19,8 @@
#include "fsi-master.h"
+#define FSI_N_SLAVES 4
+
static atomic_t master_idx = ATOMIC_INIT(-1);
struct fsi_slave {
@@ -30,12 +32,34 @@ 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)
{
master->idx = atomic_inc_return(&master_idx);
get_device(master->dev);
+ fsi_master_scan(master);
return 0;
}
EXPORT_SYMBOL_GPL(fsi_master_register);
--
1.8.2.2
^ permalink raw reply related
* [PATCH 10/16] drivers/fsi: scan slaves & register devices
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
sre-DgEjT+Ai2ygdnm+yROfE0A, mturquette-rdvid1DuHRBWk0Htik3J/w,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
alistair-Y4h6yKqj69EXC2x5gXVKYQ,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Chris Bostic
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.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-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
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 aa4330a..b51ea35 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -21,9 +21,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 atomic_t master_idx = ATOMIC_INIT(-1);
@@ -36,6 +46,30 @@ 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;
+}
+
/* crc helpers */
static const uint8_t crc4_tab[] = {
0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
@@ -59,6 +93,99 @@ uint8_t fsi_crc4(uint8_t c, uint64_t x, int bits)
/* 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 = fsi_crc4(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);
@@ -110,7 +237,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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 13/16] drivers/fsi: Set slave SMODE to init communication
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: Chris Bostic, joel, jk, linux-kernel, andrew, alistair, benh
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic@gmail.com>
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>
---
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 93de0f1..a28434b 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -34,6 +34,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;
@@ -53,8 +54,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)
{
@@ -133,6 +152,30 @@ uint8_t fsi_crc4(uint8_t c, uint64_t x, int bits)
/* 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)
{
@@ -240,6 +283,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)
{
@@ -248,6 +307,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",
@@ -312,6 +386,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);
@@ -327,6 +402,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
* [PATCH 14/16] drivers/fsi: Add master unscan
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: Chris Bostic, joel, jk, linux-kernel, andrew, alistair, benh
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic@gmail.com>
From: Chris Bostic <cbostic@us.ibm.com>
Allow a master to undo a previous scan. Should a master scan a bus
twice it will need to ensure it doesn't double register any
previously detected device.
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
drivers/fsi/fsi-core.c | 36 +++++++++++++++++++++++++++++++++++-
drivers/fsi/fsi-master.h | 2 ++
include/linux/fsi.h | 1 +
3 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index a28434b..8ccfe50 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -41,6 +41,8 @@
static atomic_t master_idx = ATOMIC_INIT(-1);
struct fsi_slave {
+ struct list_head list_link; /* Master's list of slaves */
+ struct list_head my_engines;
struct device dev;
struct fsi_master *master;
int link;
@@ -196,6 +198,8 @@ static int fsi_slave_scan(struct fsi_slave *slave)
uint32_t conf;
int rc, i;
+ INIT_LIST_HEAD(&slave->my_engines);
+
/*
* scan engines
*
@@ -264,7 +268,9 @@ static int fsi_slave_scan(struct fsi_slave *slave)
if (rc) {
dev_warn(&slave->dev, "add failed: %d\n", rc);
put_device(&dev->dev);
+ continue;
}
+ list_add(&dev->link, &slave->my_engines);
}
engine_addr += slots * engine_page_size;
@@ -357,7 +363,7 @@ static int fsi_slave_init(struct fsi_master *master,
put_device(&slave->dev);
return rc;
}
-
+ list_add(&slave->list_link, &master->my_slaves);
fsi_slave_scan(slave);
return 0;
}
@@ -388,6 +394,11 @@ static int fsi_master_scan(struct fsi_master *master)
int link, slave_id, rc;
uint32_t smode;
+ if (!master->slave_list) {
+ INIT_LIST_HEAD(&master->my_slaves);
+ master->slave_list = true;
+ }
+
for (link = 0; link < master->n_links; link++) {
rc = fsi_master_link_enable(master, link);
if (rc) {
@@ -423,9 +434,31 @@ static int fsi_master_scan(struct fsi_master *master)
return 0;
}
+static void fsi_master_unscan(struct fsi_master *master)
+{
+ struct fsi_slave *slave, *slave_tmp;
+ struct fsi_device *fsi_dev, *fsi_dev_tmp;
+
+ if (!master->slave_list)
+ return;
+
+ list_for_each_entry_safe(slave, slave_tmp, &master->my_slaves,
+ list_link) {
+ list_del(&slave->list_link);
+ list_for_each_entry_safe(fsi_dev, fsi_dev_tmp,
+ &slave->my_engines, link) {
+ list_del(&fsi_dev->link);
+ put_device(&fsi_dev->dev);
+ }
+ device_unregister(&slave->dev);
+ }
+ master->slave_list = false;
+}
+
int fsi_master_register(struct fsi_master *master)
{
master->idx = atomic_inc_return(&master_idx);
+ master->slave_list = false;
get_device(master->dev);
fsi_master_scan(master);
return 0;
@@ -434,6 +467,7 @@ int fsi_master_register(struct fsi_master *master)
void fsi_master_unregister(struct fsi_master *master)
{
+ fsi_master_unscan(master);
put_device(master->dev);
}
EXPORT_SYMBOL_GPL(fsi_master_unregister);
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index 56aad0e..454af2b 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -20,6 +20,8 @@
#include <linux/device.h>
struct fsi_master {
+ struct list_head my_slaves;
+ bool slave_list;
struct device *dev;
int idx;
int n_links;
diff --git a/include/linux/fsi.h b/include/linux/fsi.h
index 66bce48..924502b 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -18,6 +18,7 @@
#include <linux/device.h>
struct fsi_device {
+ struct list_head link; /* for slave's list */
struct device dev;
u8 engine_type;
u8 version;
--
1.8.2.2
^ permalink raw reply related
* [PATCH 15/16] drivers/fsi: Add documentation for GPIO bindings
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: Chris Bostic, joel, jk, linux-kernel, andrew, alistair, benh
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic@gmail.com>
From: Chris Bostic <cbostic@us.ibm.com>
Add fsi master gpio device tree binding documentation
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
.../devicetree/bindings/fsi/fsi-master-gpio.txt | 21 +++++++++++++++++++++
1 file changed, 21 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..ff3a62e
--- /dev/null
+++ b/Documentation/devicetree/bindings/fsi/fsi-master-gpio.txt
@@ -0,0 +1,21 @@
+Device-tree bindings for gpio-based FSI master driver
+-----------------------------------------------------
+
+Required properties:
+ - compatible = "ibm,fsi-master-gpio";
+ - clk-gpios;
+ - data-gpios;
+
+Optional properties:
+ - enable-gpios;
+ - trans-gpios;
+ - mux-gpios;
+
+fsi-master {
+ compatible = "ibm,fsi-master", "ibm,fsi-master-gpio";
+ clk-gpios = <&gpio 0 &gpio 6>;
+ data-gpios = <&gpio 1 &gpio 7>;
+ enable-gpios = <&gpio 2 &gpio 8>; /* Enable FSI data in/out */
+ trans-gpios = <&gpio 3 &gpio 9>; /* Volts translator direction */
+ mux-gpios = <&gpio 4> &gpio 10>; /* Multiplexer for FSI pins */
+}
--
1.8.2.2
^ permalink raw reply related
* [PATCH 16/16] drivers/fsi: Add GPIO based FSI master
From: Chris Bostic @ 2016-12-07 0:14 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: Chris Bostic, joel, jk, linux-kernel, andrew, alistair, benh
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic@gmail.com>
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 | 7 +
drivers/fsi/Makefile | 1 +
drivers/fsi/fsi-master-gpio.c | 552 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 560 insertions(+)
create mode 100644 drivers/fsi/fsi-master-gpio.c
diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index f065dbe..9530459 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -17,6 +17,13 @@ config FSI_MASTER_FAKE
depends on FSI
---help---
This option enables a fake FSI master driver for debugging.
+
+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 847c00c..2021ce5 100644
--- a/drivers/fsi/Makefile
+++ b/drivers/fsi/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_FSI) += fsi-core.o
obj-$(CONFIG_FSI_MASTER_FAKE) += fsi-master-fake.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..79cb0b1
--- /dev/null
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -0,0 +1,552 @@
+/*
+ * 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 "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 = fsi_crc4(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 = fsi_crc4(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 void fsi_master_gpio_init(struct fsi_master_gpio *master)
+{
+ if (master->gpio_mux)
+ gpiod_direction_output(master->gpio_mux, 1);
+ if (master->gpio_trans)
+ gpiod_direction_output(master->gpio_trans, 1);
+ if (master->gpio_enable)
+ gpiod_direction_output(master->gpio_enable, 1);
+ gpiod_direction_output(master->gpio_clk, 1);
+ gpiod_direction_output(master->gpio_data, 1);
+
+ /* todo: evaluate if clocks can be reduced */
+ clock_toggle(master, FSI_INIT_CLOCKS);
+}
+
+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 ssize_t store_scan(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct fsi_master_gpio *master = dev_get_drvdata(dev);
+
+ fsi_master_gpio_init(master);
+
+ /* clear out any old scan data if present */
+ fsi_master_unregister(&master->master);
+ fsi_master_register(&master->master);
+
+ return count;
+}
+
+static DEVICE_ATTR(scan, 0200, NULL, store_scan);
+
+static int fsi_master_gpio_probe(struct platform_device *pdev)
+{
+ struct fsi_master_gpio *master;
+ struct gpio_desc *gpio;
+
+ master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL);
+ if (!master)
+ return -ENOMEM;
+
+ gpio = devm_gpiod_get(&pdev->dev, "clock", 0);
+ if (IS_ERR(gpio)) {
+ dev_dbg(&pdev->dev, "probe: failed to get clock pin\n");
+ return PTR_ERR(gpio);
+ }
+ master->gpio_clk = gpio;
+
+ gpio = devm_gpiod_get(&pdev->dev, "data", 0);
+ if (IS_ERR(gpio)) {
+ dev_dbg(&pdev->dev, "probe: failed to get data pin\n");
+ return PTR_ERR(gpio);
+ }
+ master->gpio_data = gpio;
+
+ /* Optional pins */
+
+ gpio = devm_gpiod_get(&pdev->dev, "trans", 0);
+ if (IS_ERR(gpio))
+ dev_dbg(&pdev->dev, "probe: failed to get trans pin\n");
+ else
+ master->gpio_trans = gpio;
+
+ gpio = devm_gpiod_get(&pdev->dev, "enable", 0);
+ if (IS_ERR(gpio))
+ dev_dbg(&pdev->dev, "probe: failed to get enable pin\n");
+ else
+ master->gpio_enable = gpio;
+
+ gpio = devm_gpiod_get(&pdev->dev, "mux", 0);
+ if (IS_ERR(gpio))
+ dev_dbg(&pdev->dev, "probe: failed to get mux pin\n");
+ else
+ master->gpio_mux = gpio;
+
+ 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;
+ platform_set_drvdata(pdev, master);
+
+ return device_create_file(&pdev->dev, &dev_attr_scan);
+}
+
+
+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
* Re: [PATCH v5 2/2] i2c: aspeed: added documentation for Aspeed I2C driver
From: Vladimir Zapolskiy @ 2016-12-07 0:19 UTC (permalink / raw)
To: Brendan Higgins, wsa-z923LK4zBo2bacvFa/9K2g, clg-Bxea+6Xhats,
mouse-Pma6HLj0uuo, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8
Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, joel-U3u1mxZcP9KHXe+LvDLADg,
openbmc-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1480467618-7497-3-git-send-email-brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Hello Brendan,
please find review comments below.
On 11/30/2016 03:00 AM, Brendan Higgins wrote:
> Added device tree binding documentation for Aspeed I2C controller and
> busses.
This is not the exact description of the added bindings, here you add two
device tree bindings of interrupt controller device and I2C bus controller
device.
Please separate the description into two separate files, place one into
../interrupt-controller/aspeed,ast2400-i2c-ic.txt and another one into
../i2c/aspeed,ast2400-i2c.txt file
The description of device tree bindings must precede the actual drivers,
assuming that the file with two drivers is also split into two files
there should be 4 patches for v6:
1) device tree description of the interrupt controller,
2) interrupt controller driver,
3) device tree description of the I2C bus controller,
4) I2C bus controller driver.
> Signed-off-by: Brendan Higgins <brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
> ---
> Changes for v2:
> - None
> Changes for v3:
> - Removed reference to "bus" device tree param
> Changes for v4:
> - None
> Changes for v5:
> - None
> ---
> .../devicetree/bindings/i2c/i2c-aspeed.txt | 61 ++++++++++++++++++++++
> 1 file changed, 61 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
> new file mode 100644
> index 0000000..dd11a97
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
> @@ -0,0 +1,61 @@
> +Device tree configuration for the I2C controller and busses on the AST24XX
> +and AST25XX SoCs.
> +
> +Controller:
Interrupt controller.
> +
> + Required Properties:
> + - #address-cells : should be 1
> + - #size-cells : should be 1
> + - #interrupt-cells : should be 1
> + - compatible : should be "aspeed,ast2400-i2c-controller"
> + or "aspeed,ast2500-i2c-controller"
> + - reg : address start and range of controller
> + - ranges : defines address offset and range for busses
> + - interrupts : interrupt number
> + - clocks : root clock of bus, should reference the APB
> + clock
> + - clock-ranges : specifies that child busses can inherit clocks
> + - interrupt-controller : denotes that the controller receives and fires
> + new interrupts for child busses
> +
> +Bus:
I2C bus controller.
> +
> + Required Properties:
> + - #address-cells : should be 1
> + - #size-cells : should be 0
> + - reg : address offset and range of bus
> + - compatible : should be "aspeed,ast2400-i2c-bus"
> + or "aspeed,ast2500-i2c-bus"
> + - interrupts : interrupt number
> +
> + Optional Properties:
> + - clock-frequency : frequency of the bus clock in Hz
> + defaults to 100 kHz when not specified
> +
> +Example:
> +
> +i2c: i2c@1e78a000 {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + #interrupt-cells = <1>;
> +
> + compatible = "aspeed,ast2400-i2c-controller";
> + reg = <0x1e78a000 0x40>;
> + ranges = <0 0x1e78a000 0x1000>;
> + interrupts = <12>;
> + clocks = <&clk_apb>;
> + clock-ranges;
> + interrupt-controller;
> +
> + i2c0: i2c-bus@40 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0x40 0x40>;
> + compatible = "aspeed,ast2400-i2c-bus";
> + clock-frequency = <100000>;
> + status = "disabled";
> + interrupts = <0>;
> + interrupt-parent = <&i2c>;
> + };
> +};
The selected layout of device tree nodes does not reflect the actual
hardware, I2C bus controller (sub-)devices can not be children of the
interrupt controller device, they are only consumers of interrupts from
the interrupt controller device.
In this case the proper and expected device tree description should
look like the one below:
i2c {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x1e78a000 0x1000>;
i2c-ic: interrupt-controller@0 {
compatible = "aspeed,ast2400-i2c-ic";
reg = <0x0 0x40>;
clocks = <&clk_apb>;
interrupt-controller;
interrupts = <12>;
#interrupt-cells = <1>;
};
i2c0: i2c@40 {
compatible = "aspeed,ast2400-i2c";
reg = <0x40 0x40>;
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <100000>;
interrupt-parent = <&i2c-ic>;
interrupts = <0>;
status = "disabled";
};
i2c1: i2c-bus@80 {
.....
};
};
--
With best wishes,
Vladimir
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V7 00/10] PM / OPP: Multiple regulator support
From: Stephen Boyd @ 2016-12-07 0:37 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael J. Wysocki, Rafael Wysocki, Lists linaro-kernel,
linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Nishanth Menon,
Vincent Guittot, Rob Herring, Dave Gerlach, Mark Brown,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20161206031502.GA31465@vireshk-i7>
On 12/06, Viresh Kumar wrote:
> On 06-12-16, 02:34, Rafael J. Wysocki wrote:
> > I've queued them up, but I'd feel more comfortable with an ACK or
> > Reviewed-by on patch [6/10] too.
>
> Sure. I would still encourage Stephen to do it. Seems he is very busy now a days
> :)
Yep, there's never enough emails to read!
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V7 06/10] PM / OPP: Add infrastructure to manage multiple regulators
From: Stephen Boyd @ 2016-12-07 0:39 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, Viresh Kumar, Nishanth Menon, linaro-kernel,
linux-pm, Vincent Guittot, robh, d-gerlach, broonie, devicetree
In-Reply-To: <804d4f89c517f7a0b0bb98ef513c329fd5f76d39.1480564564.git.viresh.kumar@linaro.org>
On 12/01, Viresh Kumar wrote:
> This patch adds infrastructure to manage multiple regulators and updates
> the only user (cpufreq-dt) of dev_pm_opp_set{put}_regulator().
>
> This is preparatory work for adding full support for devices with
> multiple regulators.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> Tested-by: Dave Gerlach <d-gerlach@ti.com>
> ---
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [RFC PATCH v3 2/2] drm/panel: Add support for Chunghwa CLAA070WP03XG panel
From: Ayaka @ 2016-12-07 0:57 UTC (permalink / raw)
To: Thierry Reding
Cc: dri-devel, linux, kgene, krzk, linux-arm-kernel,
linux-samsung-soc, linux-kernel, airlied, a.hajda, devicetree
In-Reply-To: <20161206154625.GA28534@ulmo.ba.sec>
從我的 iPad 傳送
> Thierry Reding <thierry.reding@gmail.com> 於 2016年12月6日 下午11:46 寫道:
>
>> On Tue, Sep 20, 2016 at 03:02:51AM +0800, Randy Li wrote:
>> The Chunghwa CLAA070WP03XG is a 7" 1280x800 panel, which can be
>> supported by the simple panel driver.
>>
>> Signed-off-by: Randy Li <ayaka@soulik.info>
>> ---
>> .../display/panel/chunghwa,claa070wp03xg.txt | 7 ++++++
>> drivers/gpu/drm/panel/panel-simple.c | 27 ++++++++++++++++++++++
>> 2 files changed, 34 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt
>
> Applied, thanks.
Wait, it is RFC, not pass the test.
>
> Thierry
^ permalink raw reply
* Re: [PATCH v5 1/2] i2c: aspeed: added driver for Aspeed I2C
From: Vladimir Zapolskiy @ 2016-12-07 0:57 UTC (permalink / raw)
To: Brendan Higgins, wsa-z923LK4zBo2bacvFa/9K2g, clg-Bxea+6Xhats,
mouse-Pma6HLj0uuo, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8
Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, joel-U3u1mxZcP9KHXe+LvDLADg,
openbmc-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1480467618-7497-2-git-send-email-brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Hello Brendan,
please find review comments below.
After reviewing device tree binding now I'm confident that you should split
the file into two and then send interrupt controller driver for a separate
review by IRQCHIP maintainers. The interrupt controller driver will be
quite simple (as almost all of them), but it deserves its own review
and it should be placed under drivers/irqchip.
On 11/30/2016 03:00 AM, Brendan Higgins wrote:
> Added initial master and slave support for Aspeed I2C controller.
> Supports fourteen busses present in ast24xx and ast25xx BMC SoCs by
> Aspeed.
>
> Signed-off-by: Brendan Higgins <brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
> ---
> Changes for v2:
> - Added single module_init (multiple was breaking some builds).
> Changes for v3:
> - Removed "bus" device tree param; now extracted from bus address offset
> Changes for v4:
> - I2C adapter number is now generated dynamically unless specified in alias.
> Changes for v5:
> - Removed irq_chip used to multiplex IRQ and replaced it with dummy_irq_chip
> along with some other IRQ cleanup.
> - Addressed comments from Cedric, and Vladimir, mostly stylistic things and
> using devm managed resources.
> - Increased max clock frequency before the bus is put in HighSpeed mode, as
> per Kachalov's comment.
> ---
> drivers/i2c/busses/Kconfig | 10 +
> drivers/i2c/busses/Makefile | 1 +
> drivers/i2c/busses/i2c-aspeed.c | 839 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 850 insertions(+)
> create mode 100644 drivers/i2c/busses/i2c-aspeed.c
>
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index d252276..e8cf750 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -325,6 +325,16 @@ config I2C_POWERMAC
>
> comment "I2C system bus drivers (mostly embedded / system-on-chip)"
>
> +config I2C_ASPEED
> + tristate "Aspeed AST2xxx SoC I2C Controller"
> + depends on ARCH_ASPEED
> + help
> + If you say yes to this option, support will be included for the
> + Aspeed AST2xxx SoC I2C controller.
> +
> + This driver can also be built as a module. If so, the module
> + will be called i2c-aspeed.
> +
> config I2C_AT91
> tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
> depends on ARCH_AT91
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 29764cc..73fec22 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -29,6 +29,7 @@ obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
> obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
>
> # Embedded system I2C/SMBus host controller drivers
> +obj-$(CONFIG_I2C_ASPEED) += i2c-aspeed.o
> obj-$(CONFIG_I2C_AT91) += i2c-at91.o
> obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
> obj-$(CONFIG_I2C_AXXIA) += i2c-axxia.o
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> new file mode 100644
> index 0000000..0e68808
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -0,0 +1,839 @@
> +/*
> + * I2C adapter for the ASPEED I2C bus.
> + *
> + * Copyright (C) 2012-2016 ASPEED Technology Inc.
> + * Copyright 2016 IBM Corporation
> + * Copyright 2016 Google, Inc.
> + *
> + * 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.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/completion.h>
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +/* I2C Register */
> +#define ASPEED_I2C_FUN_CTRL_REG 0x00
> +#define ASPEED_I2C_AC_TIMING_REG1 0x04
> +#define ASPEED_I2C_AC_TIMING_REG2 0x08
> +#define ASPEED_I2C_INTR_CTRL_REG 0x0c
> +#define ASPEED_I2C_INTR_STS_REG 0x10
> +#define ASPEED_I2C_CMD_REG 0x14
> +#define ASPEED_I2C_DEV_ADDR_REG 0x18
> +#define ASPEED_I2C_BYTE_BUF_REG 0x20
> +
> +#define ASPEED_I2C_NUM_BUS 14
> +
> +/* Global Register Definition */
> +/* 0x00 : I2C Interrupt Status Register */
> +/* 0x08 : I2C Interrupt Target Assignment */
> +
> +/* Device Register Definition */
> +/* 0x00 : I2CD Function Control Register */
> +#define ASPEED_I2CD_MULTI_MASTER_DIS BIT(15)
> +#define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8)
> +#define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7)
> +#define ASPEED_I2CD_M_HIGH_SPEED_EN BIT(6)
> +#define ASPEED_I2CD_SLAVE_EN BIT(1)
> +#define ASPEED_I2CD_MASTER_EN BIT(0)
> +
> +/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
> +#define ASPEED_NO_TIMEOUT_CTRL 0
> +
> +
checkpatch complains here:
CHECK: Please don't use multiple blank lines
#60: FILE: drivers/i2c/busses/i2c-aspeed.c:60:
> +/* 0x0c : I2CD Interrupt Control Register &
> + * 0x10 : I2CD Interrupt Status Register
> + *
> + * These share bit definitions, so use the same values for the enable &
> + * status bits.
> + */
> +#define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14)
> +#define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13)
> +#define ASPEED_I2CD_INTR_SLAVE_MATCH BIT(7)
> +#define ASPEED_I2CD_INTR_SCL_TIMEOUT BIT(6)
> +#define ASPEED_I2CD_INTR_ABNORMAL BIT(5)
> +#define ASPEED_I2CD_INTR_NORMAL_STOP BIT(4)
> +#define ASPEED_I2CD_INTR_ARBIT_LOSS BIT(3)
> +#define ASPEED_I2CD_INTR_RX_DONE BIT(2)
> +#define ASPEED_I2CD_INTR_TX_NAK BIT(1)
> +#define ASPEED_I2CD_INTR_TX_ACK BIT(0)
> +#define ASPEED_I2CD_INTR_ERROR \
> + (ASPEED_I2CD_INTR_ARBIT_LOSS | \
> + ASPEED_I2CD_INTR_ABNORMAL | \
> + ASPEED_I2CD_INTR_SCL_TIMEOUT | \
> + ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \
> + ASPEED_I2CD_INTR_TX_NAK)
> +#define ASPEED_I2CD_INTR_ALL \
> + (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \
> + ASPEED_I2CD_INTR_BUS_RECOVER_DONE | \
> + ASPEED_I2CD_INTR_SCL_TIMEOUT | \
> + ASPEED_I2CD_INTR_ABNORMAL | \
> + ASPEED_I2CD_INTR_NORMAL_STOP | \
> + ASPEED_I2CD_INTR_ARBIT_LOSS | \
> + ASPEED_I2CD_INTR_RX_DONE | \
> + ASPEED_I2CD_INTR_TX_NAK | \
> + ASPEED_I2CD_INTR_TX_ACK)
> +
> +/* 0x14 : I2CD Command/Status Register */
> +#define ASPEED_I2CD_SCL_LINE_STS BIT(18)
> +#define ASPEED_I2CD_SDA_LINE_STS BIT(17)
> +#define ASPEED_I2CD_BUS_BUSY_STS BIT(16)
> +#define ASPEED_I2CD_BUS_RECOVER_CMD BIT(11)
> +
> +/* Command Bit */
> +#define ASPEED_I2CD_M_STOP_CMD BIT(5)
> +#define ASPEED_I2CD_M_S_RX_CMD_LAST BIT(4)
> +#define ASPEED_I2CD_M_RX_CMD BIT(3)
> +#define ASPEED_I2CD_S_TX_CMD BIT(2)
> +#define ASPEED_I2CD_M_TX_CMD BIT(1)
> +#define ASPEED_I2CD_M_START_CMD BIT(0)
> +
> +/* 0x18 : I2CD Slave Device Address Register */
> +#define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0)
> +
> +enum aspeed_i2c_slave_state {
> + ASPEED_I2C_SLAVE_START,
> + ASPEED_I2C_SLAVE_READ_REQUESTED,
> + ASPEED_I2C_SLAVE_READ_PROCESSED,
> + ASPEED_I2C_SLAVE_WRITE_REQUESTED,
> + ASPEED_I2C_SLAVE_WRITE_RECEIVED,
> + ASPEED_I2C_SLAVE_STOP,
> +};
> +
> +struct aspeed_i2c_bus {
> + struct i2c_adapter adap;
> + struct device *dev;
> + void __iomem *base;
> + spinlock_t lock;
checkpatch complains here:
CHECK: spinlock_t definition without comment
#124: FILE: drivers/i2c/busses/i2c-aspeed.c:124:
> + struct completion cmd_complete;
> + int irq;
> + /* Transaction state. */
> + struct i2c_msg *msg;
> + int msg_pos;
> + u32 cmd_err;
> +#if IS_ENABLED(CONFIG_I2C_SLAVE)
> + struct i2c_client *slave;
> + enum aspeed_i2c_slave_state slave_state;
> +#endif
> +};
> +
> +struct aspeed_i2c_controller {
> + struct device *dev;
> + void __iomem *base;
> + int irq;
> + struct irq_domain *irq_domain;
> +};
> +
> +static inline void aspeed_i2c_write(struct aspeed_i2c_bus *bus, u32 val,
> + u32 reg)
> +{
> + writel(val, bus->base + reg);
> +}
> +
> +static inline u32 aspeed_i2c_read(struct aspeed_i2c_bus *bus, u32 reg)
> +{
> + return readl(bus->base + reg);
> +}
> +
> +static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> +{
> + unsigned long time_left, flags;
> + int ret = 0;
> + u32 command;
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + command = aspeed_i2c_read(bus, ASPEED_I2C_CMD_REG);
> +
> + if (command & ASPEED_I2CD_SDA_LINE_STS) {
> + /* Bus is idle: no recovery needed. */
> + if (command & ASPEED_I2CD_SCL_LINE_STS)
> + goto out;
> + dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
> + command);
> +
> + aspeed_i2c_write(bus, ASPEED_I2CD_M_STOP_CMD,
> + ASPEED_I2C_CMD_REG);
> + reinit_completion(&bus->cmd_complete);
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + time_left = wait_for_completion_timeout(
> + &bus->cmd_complete, bus->adap.timeout);
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + if (time_left == 0)
> + ret = -ETIMEDOUT;
> + else if (bus->cmd_err)
> + ret = -EIO;
> + /* Bus error. */
> + } else {
> + dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
> + command);
> +
> + aspeed_i2c_write(bus, ASPEED_I2CD_BUS_RECOVER_CMD,
> + ASPEED_I2C_CMD_REG);
> + reinit_completion(&bus->cmd_complete);
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + time_left = wait_for_completion_timeout(
> + &bus->cmd_complete, bus->adap.timeout);
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + if (time_left == 0)
> + ret = -ETIMEDOUT;
> + else if (bus->cmd_err)
> + ret = -EIO;
> + /* Recovery failed. */
> + else if (!(aspeed_i2c_read(bus, ASPEED_I2C_CMD_REG) &
> + ASPEED_I2CD_SDA_LINE_STS))
> + ret = -EIO;
> + }
> +
> +out:
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + return ret;
> +}
> +
> +#if IS_ENABLED(CONFIG_I2C_SLAVE)
> +static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
> +{
> + u32 command, irq_status, status_ack = 0;
> + struct i2c_client *slave = bus->slave;
> + bool irq_handled = true;
> + u8 value;
> +
> + spin_lock(&bus->lock);
> + if (!slave) {
> + irq_handled = false;
> + goto out;
> + }
> +
> + command = aspeed_i2c_read(bus, ASPEED_I2C_CMD_REG);
> + irq_status = aspeed_i2c_read(bus, ASPEED_I2C_INTR_STS_REG);
> +
> + /* Slave was requested, restart state machine. */
> + if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) {
> + status_ack |= ASPEED_I2CD_INTR_SLAVE_MATCH;
> + bus->slave_state = ASPEED_I2C_SLAVE_START;
> + }
> +
> + /* Slave is not currently active, irq was for someone else. */
> + if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) {
> + irq_handled = false;
> + goto out;
> + }
> +
> + dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
> + irq_status, command);
> +
> + /* Slave was sent something. */
> + if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
> + value = aspeed_i2c_read(bus, ASPEED_I2C_BYTE_BUF_REG) >> 8;
> + /* Handle address frame. */
> + if (bus->slave_state == ASPEED_I2C_SLAVE_START) {
> + if (value & 0x1)
> + bus->slave_state =
> + ASPEED_I2C_SLAVE_READ_REQUESTED;
> + else
> + bus->slave_state =
> + ASPEED_I2C_SLAVE_WRITE_REQUESTED;
> + }
> + status_ack |= ASPEED_I2CD_INTR_RX_DONE;
> + }
> +
> + /* Slave was asked to stop. */
> + if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
> + status_ack |= ASPEED_I2CD_INTR_NORMAL_STOP;
> + bus->slave_state = ASPEED_I2C_SLAVE_STOP;
> + }
> + if (irq_status & ASPEED_I2CD_INTR_TX_NAK) {
> + status_ack |= ASPEED_I2CD_INTR_TX_NAK;
> + bus->slave_state = ASPEED_I2C_SLAVE_STOP;
> + }
> +
> + switch (bus->slave_state) {
> + case ASPEED_I2C_SLAVE_READ_REQUESTED:
> + if (irq_status & ASPEED_I2CD_INTR_TX_ACK)
> + dev_err(bus->dev, "Unexpected ACK on read request.\n");
> + bus->slave_state = ASPEED_I2C_SLAVE_READ_PROCESSED;
> +
> + i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value);
> + aspeed_i2c_write(bus, value, ASPEED_I2C_BYTE_BUF_REG);
> + aspeed_i2c_write(bus, ASPEED_I2CD_S_TX_CMD, ASPEED_I2C_CMD_REG);
> + break;
> + case ASPEED_I2C_SLAVE_READ_PROCESSED:
> + status_ack |= ASPEED_I2CD_INTR_TX_ACK;
> + if (!(irq_status & ASPEED_I2CD_INTR_TX_ACK))
> + dev_err(bus->dev,
> + "Expected ACK after processed read.\n");
> + i2c_slave_event(slave, I2C_SLAVE_READ_PROCESSED, &value);
> + aspeed_i2c_write(bus, value, ASPEED_I2C_BYTE_BUF_REG);
> + aspeed_i2c_write(bus, ASPEED_I2CD_S_TX_CMD, ASPEED_I2C_CMD_REG);
> + break;
> + case ASPEED_I2C_SLAVE_WRITE_REQUESTED:
> + bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED;
> + i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
> + break;
> + case ASPEED_I2C_SLAVE_WRITE_RECEIVED:
> + i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value);
> + break;
> + case ASPEED_I2C_SLAVE_STOP:
> + i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
> + break;
> + default:
> + dev_err(bus->dev, "unhandled slave_state: %d\n",
> + bus->slave_state);
> + break;
> + }
> +
> + if (status_ack != irq_status)
> + dev_err(bus->dev,
> + "irq handled != irq. expected %x, but was %x\n",
> + irq_status, status_ack);
> + aspeed_i2c_write(bus, status_ack, ASPEED_I2C_INTR_STS_REG);
> +
> +out:
> + spin_unlock(&bus->lock);
> + return irq_handled;
> +}
> +#endif
> +
> +static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
> +{
> + u32 irq_status;
> +
> + spin_lock(&bus->lock);
> + irq_status = aspeed_i2c_read(bus, ASPEED_I2C_INTR_STS_REG);
> + bus->cmd_err = irq_status & ASPEED_I2CD_INTR_ERROR;
> +
> + dev_dbg(bus->dev, "master irq status 0x%08x\n", irq_status);
> +
> + /* No message to transfer. */
> + if (bus->cmd_err ||
> + (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) ||
> + (irq_status & ASPEED_I2CD_INTR_BUS_RECOVER_DONE)) {
> + complete(&bus->cmd_complete);
> + goto out;
> + } else if (!bus->msg || bus->msg_pos >= bus->msg->len)
> + goto out;
checkpatch complains here:
CHECK: braces {} should be used on all arms of this statement
#329: FILE: drivers/i2c/busses/i2c-aspeed.c:329:
> +
> + if ((bus->msg->flags & I2C_M_RD) &&
> + (irq_status & ASPEED_I2CD_INTR_RX_DONE)) {
> + bus->msg->buf[bus->msg_pos++] = aspeed_i2c_read(
> + bus, ASPEED_I2C_BYTE_BUF_REG) >> 8;
> + if (bus->msg_pos + 1 < bus->msg->len)
> + aspeed_i2c_write(bus, ASPEED_I2CD_M_RX_CMD,
> + ASPEED_I2C_CMD_REG);
> + else if (bus->msg_pos < bus->msg->len)
> + aspeed_i2c_write(bus, ASPEED_I2CD_M_RX_CMD |
> + ASPEED_I2CD_M_S_RX_CMD_LAST,
> + ASPEED_I2C_CMD_REG);
> + } else if (!(bus->msg->flags & I2C_M_RD) &&
> + (irq_status & ASPEED_I2CD_INTR_TX_ACK)) {
> + aspeed_i2c_write(bus, bus->msg->buf[bus->msg_pos++],
> + ASPEED_I2C_BYTE_BUF_REG);
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#351: FILE: drivers/i2c/busses/i2c-aspeed.c:351:
> + aspeed_i2c_write(bus, ASPEED_I2CD_M_TX_CMD, ASPEED_I2C_CMD_REG);
> + }
> +
> + /* Transmission complete: notify caller. */
> + if (bus->msg_pos >= bus->msg->len)
> + complete(&bus->cmd_complete);
> +out:
> + aspeed_i2c_write(bus, irq_status, ASPEED_I2C_INTR_STS_REG);
> + spin_unlock(&bus->lock);
> +
> + return true;
> +}
> +
> +static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
> +{
> + struct aspeed_i2c_bus *bus = dev_id;
> +
> +#if IS_ENABLED(CONFIG_I2C_SLAVE)
> + if (aspeed_i2c_slave_irq(bus)) {
> + dev_dbg(bus->dev, "irq handled by slave.\n");
> + return IRQ_HANDLED;
> + }
> +#endif
> +
> + if (aspeed_i2c_master_irq(bus)) {
> + dev_dbg(bus->dev, "irq handled by master.\n");
> + return IRQ_HANDLED;
> + }
aspeed_i2c_master_irq() always return 'true', this means that
without functional change you can move dev_dbg() into
aspeed_i2c_master_irq() function, and then remove the if-check
for return value.
> +
> + dev_err(bus->dev, "irq not handled properly!\n");
> + return IRQ_NONE;
This is dead code, if functional changes in aspeed_i2c_master_irq()
are not done, please remove it.
> +}
> +
> +static int aspeed_i2c_master_single_xfer(struct i2c_adapter *adap,
> + struct i2c_msg *msg)
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#386: FILE: drivers/i2c/busses/i2c-aspeed.c:386:
> +{
> + u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD;
> + struct aspeed_i2c_bus *bus = adap->algo_data;
> + unsigned long time_left, flags;
> + int ret = msg->len;
> + u8 slave_addr;
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + bus->msg = msg;
> + bus->msg_pos = 0;
> + slave_addr = msg->addr << 1;
> +
> + if (msg->flags & I2C_M_RD) {
> + slave_addr |= 1;
> + command |= ASPEED_I2CD_M_RX_CMD;
> + if (msg->len == 1)
> + command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
> + }
> +
> + aspeed_i2c_write(bus, slave_addr, ASPEED_I2C_BYTE_BUF_REG);
> + aspeed_i2c_write(bus, command, ASPEED_I2C_CMD_REG);
> + reinit_completion(&bus->cmd_complete);
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + time_left = wait_for_completion_timeout(
> + &bus->cmd_complete, bus->adap.timeout);
> + if (time_left == 0)
> + return -ETIMEDOUT;
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + if (bus->cmd_err)
> + ret = -EIO;
> +
> + bus->msg = NULL;
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + return ret;
> +}
> +
> +static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
> + struct i2c_msg *msgs, int num)
> +{
> + struct aspeed_i2c_bus *bus = adap->algo_data;
> + unsigned long time_left, flags;
> + int ret, i;
> +
> + /* If bus is busy, attempt recovery. We assume a single master
> + * environment.
> + */
> + if (aspeed_i2c_read(bus, ASPEED_I2C_CMD_REG) &
> + ASPEED_I2CD_BUS_BUSY_STS) {
> + ret = aspeed_i2c_recover_bus(bus);
> + if (ret)
> + return ret;
> + }
> +
> + for (i = 0; i < num; i++) {
> + ret = aspeed_i2c_master_single_xfer(adap, &msgs[i]);
> + if (ret < 0)
> + break;
Please insert an empty line here to improve readability.
> + /* TODO: Support other forms of I2C protocol mangling. */
> + if (msgs[i].flags & I2C_M_STOP) {
> + spin_lock_irqsave(&bus->lock, flags);
> + aspeed_i2c_write(bus, ASPEED_I2CD_M_STOP_CMD,
> + ASPEED_I2C_CMD_REG);
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#451: FILE: drivers/i2c/busses/i2c-aspeed.c:451:
> + reinit_completion(&bus->cmd_complete);
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + time_left = wait_for_completion_timeout(
> + &bus->cmd_complete, bus->adap.timeout);
> + if (time_left == 0)
> + return -ETIMEDOUT;
> + }
> + }
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + aspeed_i2c_write(bus, ASPEED_I2CD_M_STOP_CMD, ASPEED_I2C_CMD_REG);
> + reinit_completion(&bus->cmd_complete);
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + time_left = wait_for_completion_timeout(
> + &bus->cmd_complete, bus->adap.timeout);
> + if (time_left == 0)
> + return -ETIMEDOUT;
> +
> + /* If nothing went wrong, return number of messages transferred. */
> + if (ret < 0)
> + return ret;
> + else
> + return i;
> +}
> +
> +static u32 aspeed_i2c_functionality(struct i2c_adapter *adap)
> +{
> + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
> +}
> +
> +#if IS_ENABLED(CONFIG_I2C_SLAVE)
> +static int aspeed_i2c_reg_slave(struct i2c_client *client)
> +{
> + u32 addr_reg_val, func_ctrl_reg_val;
> + struct aspeed_i2c_bus *bus;
> + unsigned long flags;
> +
> + bus = client->adapter->algo_data;
> + spin_lock_irqsave(&bus->lock, flags);
> + if (bus->slave) {
> + spin_unlock_irqrestore(&bus->lock, flags);
> + return -EINVAL;
> + }
> +
> + /* Set slave addr. */
> + addr_reg_val = aspeed_i2c_read(bus, ASPEED_I2C_DEV_ADDR_REG);
> + addr_reg_val &= ~ASPEED_I2CD_DEV_ADDR_MASK;
> + addr_reg_val |= client->addr & ASPEED_I2CD_DEV_ADDR_MASK;
> + aspeed_i2c_write(bus, addr_reg_val, ASPEED_I2C_DEV_ADDR_REG);
> +
> + /* Switch from master mode to slave mode. */
> + func_ctrl_reg_val = aspeed_i2c_read(bus, ASPEED_I2C_FUN_CTRL_REG);
> + func_ctrl_reg_val &= ~ASPEED_I2CD_MASTER_EN;
> + func_ctrl_reg_val |= ASPEED_I2CD_SLAVE_EN;
> + aspeed_i2c_write(bus, func_ctrl_reg_val, ASPEED_I2C_FUN_CTRL_REG);
> +
> + bus->slave = client;
> + bus->slave_state = ASPEED_I2C_SLAVE_STOP;
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + return 0;
> +}
> +
> +static int aspeed_i2c_unreg_slave(struct i2c_client *client)
> +{
> + struct aspeed_i2c_bus *bus = client->adapter->algo_data;
> + u32 func_ctrl_reg_val;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&bus->lock, flags);
> + if (!bus->slave) {
> + spin_unlock_irqrestore(&bus->lock, flags);
> + return -EINVAL;
> + }
> +
> + /* Switch from slave mode to master mode. */
> + func_ctrl_reg_val = aspeed_i2c_read(bus, ASPEED_I2C_FUN_CTRL_REG);
> + func_ctrl_reg_val &= ~ASPEED_I2CD_SLAVE_EN;
> + func_ctrl_reg_val |= ASPEED_I2CD_MASTER_EN;
> + aspeed_i2c_write(bus, func_ctrl_reg_val, ASPEED_I2C_FUN_CTRL_REG);
> +
> + bus->slave = NULL;
> + spin_unlock_irqrestore(&bus->lock, flags);
> +
> + return 0;
> +}
> +#endif
> +
> +static const struct i2c_algorithm aspeed_i2c_algo = {
> + .master_xfer = aspeed_i2c_master_xfer,
> + .functionality = aspeed_i2c_functionality,
> +#if IS_ENABLED(CONFIG_I2C_SLAVE)
> + .reg_slave = aspeed_i2c_reg_slave,
> + .unreg_slave = aspeed_i2c_unreg_slave,
> +#endif
> +};
> +
> +static u32 aspeed_i2c_get_clk_reg_val(u32 divider_ratio)
> +{
> + u32 scl_low, scl_high, data;
> + unsigned int inc = 0, div;
> +
> + for (div = 0; divider_ratio >= 16; div++) {
> + inc |= (divider_ratio & 1);
> + divider_ratio >>= 1;
> + }
> +
> + divider_ratio += inc;
> + scl_low = (divider_ratio >> 1) - 1;
> + scl_high = divider_ratio - scl_low - 2;
> + data = 0x77700300 | (scl_high << 16) | (scl_low << 12) | div;
> + return data;
> +}
> +
> +static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus,
> + struct platform_device *pdev)
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#569: FILE: drivers/i2c/busses/i2c-aspeed.c:569:
> +{
> + u32 clk_freq, divider_ratio;
> + struct clk *pclk;
> + int ret;
> +
> + pclk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(pclk)) {
> + dev_err(&pdev->dev, "clk_get failed\n");
> + return PTR_ERR(pclk);
> + }
> + ret = of_property_read_u32(pdev->dev.of_node,
> + "clock-frequency", &clk_freq);
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#581: FILE: drivers/i2c/busses/i2c-aspeed.c:581:
> + if (ret < 0) {
> + dev_err(&pdev->dev,
> + "Could not read clock-frequency property\n");
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#584: FILE: drivers/i2c/busses/i2c-aspeed.c:584:
> + clk_freq = 100000;
> + }
> + divider_ratio = clk_get_rate(pclk) / clk_freq;
> + /* We just need the clock rate, we don't actually use the clk object. */
> + devm_clk_put(&pdev->dev, pclk);
> +
> + /* Set AC Timing */
> + if (clk_freq / 1000 > 1000) {
> + aspeed_i2c_write(bus, aspeed_i2c_read(bus,
> + ASPEED_I2C_FUN_CTRL_REG) |
> + ASPEED_I2CD_M_HIGH_SPEED_EN |
> + ASPEED_I2CD_M_SDA_DRIVE_1T_EN |
> + ASPEED_I2CD_SDA_DRIVE_1T_EN,
> + ASPEED_I2C_FUN_CTRL_REG);
> +
> + aspeed_i2c_write(bus, 0x3, ASPEED_I2C_AC_TIMING_REG2);
> + aspeed_i2c_write(bus, aspeed_i2c_get_clk_reg_val(divider_ratio),
> + ASPEED_I2C_AC_TIMING_REG1);
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#602: FILE: drivers/i2c/busses/i2c-aspeed.c:602:
> + } else {
> + aspeed_i2c_write(bus, aspeed_i2c_get_clk_reg_val(divider_ratio),
> + ASPEED_I2C_AC_TIMING_REG1);
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#605: FILE: drivers/i2c/busses/i2c-aspeed.c:605:
> + aspeed_i2c_write(bus, ASPEED_NO_TIMEOUT_CTRL,
> + ASPEED_I2C_AC_TIMING_REG2);
> + }
> +
> + return 0;
> +}
> +
> +static int aspeed_i2c_probe_bus(struct platform_device *pdev)
> +{
> + struct aspeed_i2c_bus *bus;
> + struct resource *res;
> + int ret;
> +
> + bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
> + if (!bus)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + bus->base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(bus->base))
> + return PTR_ERR(bus->base);
> +
> + bus->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> + ret = devm_request_irq(&pdev->dev, bus->irq, aspeed_i2c_bus_irq,
> + IRQF_SHARED, dev_name(&pdev->dev), bus);
> + if (ret < 0) {
> + dev_err(&pdev->dev, "failed to request interrupt\n");
> + return ret;
> + }
> +
> + /* Initialize the I2C adapter */
> + spin_lock_init(&bus->lock);
> + init_completion(&bus->cmd_complete);
> + bus->adap.owner = THIS_MODULE;
> + bus->adap.retries = 0;
> + bus->adap.timeout = 5 * HZ;
> + bus->adap.algo = &aspeed_i2c_algo;
> + bus->adap.algo_data = bus;
> + bus->adap.dev.parent = &pdev->dev;
> + bus->adap.dev.of_node = pdev->dev.of_node;
> + snprintf(bus->adap.name, sizeof(bus->adap.name), "Aspeed i2c");
> +
> + bus->dev = &pdev->dev;
> +
> + /* reset device: disable master & slave functions */
> + aspeed_i2c_write(bus, 0, ASPEED_I2C_FUN_CTRL_REG);
> +
> + ret = aspeed_i2c_init_clk(bus, pdev);
> + if (ret < 0)
> + return ret;
> +
> + /* Enable Master Mode */
> + aspeed_i2c_write(bus, aspeed_i2c_read(bus, ASPEED_I2C_FUN_CTRL_REG) |
> + ASPEED_I2CD_MASTER_EN |
> + ASPEED_I2CD_MULTI_MASTER_DIS, ASPEED_I2C_FUN_CTRL_REG);
> +
> + /* Set interrupt generation of I2C controller */
> + aspeed_i2c_write(bus, ASPEED_I2CD_INTR_ALL, ASPEED_I2C_INTR_CTRL_REG);
> +
> + ret = i2c_add_adapter(&bus->adap);
> + if (ret < 0)
> + return ret;
> +
> + platform_set_drvdata(pdev, bus);
> +
> + dev_info(bus->dev, "i2c bus %d registered, irq %d\n",
> + bus->adap.nr, bus->irq);
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#672: FILE: drivers/i2c/busses/i2c-aspeed.c:672:
> +
> + return 0;
> +}
> +
> +static int aspeed_i2c_remove_bus(struct platform_device *pdev)
> +{
> + struct aspeed_i2c_bus *bus = platform_get_drvdata(pdev);
> +
> + i2c_del_adapter(&bus->adap);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id aspeed_i2c_bus_of_table[] = {
> + { .compatible = "aspeed,ast2400-i2c-bus", },
> + { .compatible = "aspeed,ast2500-i2c-bus", },
checkpatch complains here:
WARNING: DT compatible string "aspeed,ast2400-i2c-bus" appears un-documented -- check ./Documentation/devicetree/bindings/
#687: FILE: drivers/i2c/busses/i2c-aspeed.c:687:
WARNING: DT compatible string "aspeed,ast2500-i2c-bus" appears un-documented -- check ./Documentation/devicetree/bindings/
#688: FILE: drivers/i2c/busses/i2c-aspeed.c:688:
Device tree binding documentation must precede the driver.
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table);
> +
> +static struct platform_driver aspeed_i2c_bus_driver = {
> + .probe = aspeed_i2c_probe_bus,
> + .remove = aspeed_i2c_remove_bus,
> + .driver = {
> + .name = "ast-i2c-bus",
> + .of_match_table = aspeed_i2c_bus_of_table,
> + },
> +};
> +
> +/*
> + * The aspeed chip provides a single hardware interrupt for all of the I2C
> + * busses, so we use a dummy interrupt chip to translate this single interrupt
> + * into multiple interrupts, each associated with a single I2C bus.
> + */
> +static void aspeed_i2c_controller_irq(struct irq_desc *desc)
> +{
> + struct aspeed_i2c_controller *c = irq_desc_get_handler_data(desc);
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + unsigned long p, status;
> + unsigned int bus_irq;
> +
> + chained_irq_enter(chip, desc);
> + status = readl(c->base);
> + for_each_set_bit(p, &status, ASPEED_I2C_NUM_BUS) {
> + bus_irq = irq_find_mapping(c->irq_domain, p);
> + generic_handle_irq(bus_irq);
> + }
> + chained_irq_exit(chip, desc);
> +}
> +
> +/*
> + * Set simple handler and mark IRQ as valid. Nothing interesting to do here
> + * since we are using a dummy interrupt chip.
> + */
> +static int aspeed_i2c_map_irq_domain(struct irq_domain *domain,
> + unsigned int irq, irq_hw_number_t hwirq)
> +{
> + irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
> + irq_set_chip_data(irq, domain->host_data);
> +
> + return 0;
> +}
> +
> +static const struct irq_domain_ops aspeed_i2c_irq_domain_ops = {
> + .map = aspeed_i2c_map_irq_domain,
> +};
> +
> +static int aspeed_i2c_probe_controller(struct platform_device *pdev)
> +{
> + struct aspeed_i2c_controller *controller;
> + struct device_node *np;
> + struct resource *res;
> +
> + controller = devm_kzalloc(&pdev->dev, sizeof(*controller), GFP_KERNEL);
> + if (!controller)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + controller->base = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(controller->base))
> + return PTR_ERR(controller->base);
> +
> + controller->irq = platform_get_irq(pdev, 0);
> + if (controller->irq < 0)
> + return -ENXIO;
here it should be "return controller->irq;"
> +
> + controller->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
> + ASPEED_I2C_NUM_BUS, &aspeed_i2c_irq_domain_ops, NULL);
> + if (!controller->irq_domain)
> + return -ENOMEM;
> +
> + controller->irq_domain->name = "ast-i2c-domain";
> +
> + irq_set_chained_handler_and_data(controller->irq,
> + aspeed_i2c_controller_irq, controller);
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#767: FILE: drivers/i2c/busses/i2c-aspeed.c:767:
But due to the long name of the function this warning can be ignored.
> +
> + controller->dev = &pdev->dev;
> +
> + platform_set_drvdata(pdev, controller);
> +
> + dev_info(controller->dev, "i2c controller registered, irq %d\n",
> + controller->irq);
checkpatch complains here:
CHECK: Alignment should match open parenthesis
#774: FILE: drivers/i2c/busses/i2c-aspeed.c:774:
> +
> + for_each_child_of_node(pdev->dev.of_node, np) {
> + of_platform_device_create(np, NULL, &pdev->dev);
> + }
This should be removed, when you correct the layout of device tree nodes
as I described in the comments to v6 2/2.
> +
> + return 0;
> +}
> +
> +static int aspeed_i2c_remove_controller(struct platform_device *pdev)
> +{
> + struct aspeed_i2c_controller *controller = platform_get_drvdata(pdev);
> +
> + irq_domain_remove(controller->irq_domain);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id aspeed_i2c_controller_of_table[] = {
> + { .compatible = "aspeed,ast2400-i2c-controller", },
> + { .compatible = "aspeed,ast2500-i2c-controller", },
checkpatch complains here:
WARNING: DT compatible string "aspeed,ast2400-i2c-controller" appears un-documented -- check ./Documentation/devicetree/bindings/
#793: FILE: drivers/i2c/busses/i2c-aspeed.c:793:
WARNING: DT compatible string "aspeed,ast2500-i2c-controller" appears un-documented -- check ./Documentation/devicetree/bindings/
#794: FILE: drivers/i2c/busses/i2c-aspeed.c:794:
Device tree binding documentation must precede the driver.
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_i2c_controller_of_table);
> +
> +static struct platform_driver aspeed_i2c_controller_driver = {
> + .probe = aspeed_i2c_probe_controller,
> + .remove = aspeed_i2c_remove_controller,
> + .driver = {
> + .name = "ast-i2c-controller",
It might be good to get from the name that this is an interrupt controller
driver.
> + .of_match_table = aspeed_i2c_controller_of_table,
> + },
> +};
> +
> +static int __init aspeed_i2c_driver_init(void)
> +{
> + int ret;
> +
> + ret = platform_driver_register(&aspeed_i2c_controller_driver);
> + if (ret < 0) {
> + platform_driver_unregister(&aspeed_i2c_controller_driver);
> + return ret;
> + }
> +
> + ret = platform_driver_register(&aspeed_i2c_bus_driver);
> +
> + if (ret < 0) {
> + platform_driver_unregister(&aspeed_i2c_bus_driver);
> + platform_driver_unregister(&aspeed_i2c_controller_driver);
> + return ret;
Now it is done incorrectly, please unregister only successfully registered
device drivers.
This will be simplified after decoupling the driver into two independent
drivers.
> + }
> +
> + return 0;
> +}
> +module_init(aspeed_i2c_driver_init);
> +
> +static void __exit aspeed_i2c_driver_exit(void)
> +{
> + platform_driver_unregister(&aspeed_i2c_bus_driver);
> + platform_driver_unregister(&aspeed_i2c_controller_driver);
This will be simplified after decoupling the driver into two independent
drivers.
> +}
> +module_exit(aspeed_i2c_driver_exit);
> +
> +MODULE_AUTHOR("Brendan Higgins <brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>");
> +MODULE_DESCRIPTION("Aspeed I2C Bus Driver");
> +MODULE_LICENSE("GPL");
>From the header this is GPL v2 only driver, then please use
MODULE_LICENSE("GPL v2");
--
With best wishes,
Vladimir
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [v2,2/3] powerpc/fsl/dts: add QMan and BMan portal nodes on t1024
From: Scott Wood @ 2016-12-07 0:59 UTC (permalink / raw)
To: Madalin Bucur
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1481030019-31854-2-git-send-email-madalin.bucur-3arQi8VN3Tc@public.gmane.org>
On Tue, Dec 06, 2016 at 03:13:38PM +0200, Madalin Bucur wrote:
> Signed-off-by: Madalin Bucur <madalin.bucur-3arQi8VN3Tc@public.gmane.org>
> ---
> arch/powerpc/boot/dts/fsl/t1024qds.dts | 29 +++++++++++++++++++++++++++++
> arch/powerpc/boot/dts/fsl/t1024rdb.dts | 33 +++++++++++++++++++++++++++++++++
> 2 files changed, 62 insertions(+)
So, in patch 1/3 you add qman and bman nodes to t1023si-post.dtsi and
call it "add QMan and BMan portal nodes on t1023rdb" as if it were
board-specific (the only board-specific part is the reserved-memory
nodes, not the portals).
Then, in this patch you only touch board-specific files, and label it
"add QMan and BMan portal nodes on t1024"...
> diff --git a/arch/powerpc/boot/dts/fsl/t1024rdb.dts b/arch/powerpc/boot/dts/fsl/t1024rdb.dts
> index 302cdd2..73a6453 100644
> --- a/arch/powerpc/boot/dts/fsl/t1024rdb.dts
> +++ b/arch/powerpc/boot/dts/fsl/t1024rdb.dts
> @@ -41,6 +41,31 @@
> #size-cells = <2>;
> interrupt-parent = <&mpic>;
>
> + aliases {
> + sg_2500_aqr105_phy4 = &sg_2500_aqr105_phy4;
> + };
What does this have to do with the qman and bman portal nodes? Why is
this alias needed?
-Scott
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 00/16] FSI device driver introduction
From: Sebastian Reichel @ 2016-12-07 1:52 UTC (permalink / raw)
To: Chris Bostic
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
mturquette-rdvid1DuHRBWk0Htik3J/w,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Chris Bostic,
joel-U3u1mxZcP9KHXe+LvDLADg, jk-mnsaURCQ41sdnm+yROfE0A,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
alistair-Y4h6yKqj69EXC2x5gXVKYQ,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r
In-Reply-To: <1481069677-53660-1-git-send-email-christopher.lee.bostic-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 498 bytes --]
Hi.
On Tue, Dec 06, 2016 at 06:14:21PM -0600, Chris Bostic wrote:
> [...]
>
> 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.
>
> [...]
I would expect, that this information is added to Documentation/
and there should be Documentation/ABI/<stable or testing>/sysfs-bus-fsi
P.S.: I'm not sure, why I'm Cc'd.
-- Sebastian
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v4 2/7] MFD: add STM32 General Purpose Timer driver
From: kbuild test robot @ 2016-12-07 1:54 UTC (permalink / raw)
Cc: kbuild-all, lee.jones, robh+dt, mark.rutland, alexandre.torgue,
devicetree, linux-kernel, thierry.reding, linux-pwm, jic23,
knaack.h, lars, pmeerw, linux-iio, linux-arm-kernel,
fabrice.gasnier, gerald.baeza, arnaud.pouliquen, linus.walleij,
linaro-kernel, benjamin.gaignard, Benjamin Gaignard
In-Reply-To: <1481027929-13704-3-git-send-email-benjamin.gaignard@st.com>
[-- Attachment #1: Type: text/plain, Size: 2333 bytes --]
Hi Benjamin,
[auto build test ERROR on iio/togreg]
[also build test ERROR on v4.9-rc8]
[cannot apply to next-20161206]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Benjamin-Gaignard/Add-PWM-and-IIO-timer-drivers-for-STM32/20161207-025220
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
config: sparc-allmodconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=sparc
All errors (new ones prefixed by >>):
WARNING: modpost: missing MODULE_LICENSE() in drivers/media/dvb-frontends/gp8psk-fe.o
see include/linux/module.h for more information
drivers/mfd/stm32-gptimer: struct of_device_id is 200 bytes. The last of 1 is:
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x73 0x74 0x2c 0x73 0x74 0x6d 0x33 0x32 0x2d 0x67 0x70 0x74 0x69 0x6d 0x65 0x72 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
>> FATAL: drivers/mfd/stm32-gptimer: struct of_device_id is not terminated with a NULL entry!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47897 bytes --]
^ permalink raw reply
* [PATCH 04/16] drivers/fsi: Add fsi master definition
From: Chris Bostic @ 2016-12-07 2:09 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
sre-DgEjT+Ai2ygdnm+yROfE0A, mturquette-rdvid1DuHRBWk0Htik3J/w,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
alistair-Y4h6yKqj69EXC2x5gXVKYQ,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Chris Bostic
From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
drivers/fsi/fsi-core.c | 20 ++++++++++++++++++++
drivers/fsi/fsi-master.h | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 57 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..ce9428d 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -17,6 +17,26 @@
#include <linux/fsi.h>
#include <linux/module.h>
+#include "fsi-master.h"
+
+static atomic_t master_idx = ATOMIC_INIT(-1);
+
+/* FSI master support */
+
+int fsi_master_register(struct fsi_master *master)
+{
+ master->idx = atomic_inc_return(&master_idx);
+ get_device(master->dev);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fsi_master_register);
+
+void fsi_master_unregister(struct fsi_master *master)
+{
+ put_device(master->dev);
+}
+EXPORT_SYMBOL_GPL(fsi_master_unregister);
+
/* FSI core & Linux bus type definitions */
static int fsi_bus_match(struct device *dev, struct device_driver *drv)
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
new file mode 100644
index 0000000..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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 08/16] drivers/fsi: Add crc4 helpers
From: Chris Bostic @ 2016-12-07 2:09 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
Chris Bostic
In-Reply-To: <1481076574-54711-1-git-send-email-christopher.lee.bostic@gmail.com>
From: Jeremy Kerr <jk@ozlabs.org>
Add some helpers for the crc checks for the slave configuration table.
This works 4-bits-at-a-time, using a simple table approach.
We will need this in the FSI core code, as well as any master
implementations that need to calculate CRCs in software.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Chris Bostic <cbostic@us.ibm.com>
---
drivers/fsi/fsi-core.c | 21 +++++++++++++++++++++
drivers/fsi/fsi-master.h | 21 +++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index ceaf536..f0832c7 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -32,6 +32,27 @@ struct fsi_slave {
#define to_fsi_slave(d) container_of(d, struct fsi_slave, dev)
+/* crc helpers */
+static const uint8_t crc4_tab[] = {
+ 0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
+ 0x1, 0x6, 0xf, 0x8, 0xa, 0xd, 0x4, 0x3,
+};
+
+uint8_t fsi_crc4(uint8_t c, uint64_t x, int bits)
+{
+ int i;
+
+ /* Align to 4-bits */
+ bits = (bits + 3) & ~0x3;
+
+ /* Calculate crc4 over four-bit nibbles, starting at the MSbit */
+ for (i = bits; i >= 0; i -= 4)
+ c = crc4_tab[c ^ ((x >> i) & 0xf)];
+
+ return c;
+}
+EXPORT_SYMBOL_GPL(fsi_crc4);
+
/* FSI slave support */
static int fsi_slave_init(struct fsi_master *master,
int link, uint8_t slave_id)
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index e75a810..cafb433 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -34,4 +34,25 @@ struct fsi_master {
extern int fsi_master_register(struct fsi_master *master);
extern void fsi_master_unregister(struct fsi_master *master);
+/**
+ * crc4 helper: Given a starting crc4 state @c, calculate the crc4 vaue of @x,
+ * which is @bits in length. This may be required by master implementations
+ * that do not provide their own hardware checksums.
+ *
+ * The crc4 is performed on 4-bit chunks (which is all we need for FSI
+ * calculations). Typically, we'll want a starting state of 0:
+ *
+ * c = fsi_crc4(0, msg, len);
+ *
+ * To crc4 a message that includes a single start bit, initialise crc4 state
+ * with:
+ *
+ * c = fsi_crc4(0, 1, 1);
+ *
+ * Then update with message data:
+ *
+ * c = fsi_crc4(c, msg, len);
+ */
+uint8_t fsi_crc4(uint8_t c, uint64_t x, int bits);
+
#endif /* DRIVERS_FSI_MASTER_H */
--
1.8.2.2
^ permalink raw reply related
* [PATCH 09/16] drivers/fsi: Implement slave initialisation
From: Chris Bostic @ 2016-12-07 2:09 UTC (permalink / raw)
To: robh+dt, mark.rutland, linux, gregkh, sre, mturquette,
geert+renesas, devicetree, linux-arm-kernel
Cc: Jeremy Kerr, joel, linux-kernel, andrew, alistair, benh,
Chris Bostic
In-Reply-To: <1481076574-54711-1-git-send-email-christopher.lee.bostic@gmail.com>
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 | 55 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 53 insertions(+), 2 deletions(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index f0832c7..aa4330a 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -16,10 +16,14 @@
#include <linux/device.h>
#include <linux/fsi.h>
#include <linux/module.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 atomic_t master_idx = ATOMIC_INIT(-1);
@@ -54,12 +58,59 @@ uint8_t fsi_crc4(uint8_t c, uint64_t x, int bits)
EXPORT_SYMBOL_GPL(fsi_crc4);
/* 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 = fsi_crc4(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
* [PATCH 11/16] drivers/fsi: Add device read/write/peek functions
From: Chris Bostic @ 2016-12-07 2:09 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
sre-DgEjT+Ai2ygdnm+yROfE0A, mturquette-rdvid1DuHRBWk0Htik3J/w,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
alistair-Y4h6yKqj69EXC2x5gXVKYQ,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Chris Bostic
In-Reply-To: <1481076574-54711-1-git-send-email-christopher.lee.bostic-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
This change introduces the fsi device API: simple read, write and peek
accessors for the devices' address spaces.
Includes contributions from Chris Bostic <cbostic-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
drivers/fsi/fsi-core.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fsi.h | 7 ++++++-
2 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index b51ea35..80feeb8 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -33,6 +33,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 atomic_t master_idx = ATOMIC_INIT(-1);
@@ -46,8 +48,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);
@@ -100,6 +140,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..66bce48 100644
--- a/include/linux/fsi.h
+++ b/include/linux/fsi.h
@@ -27,6 +27,12 @@ struct fsi_device {
uint32_t size;
};
+extern int fsi_device_read(struct fsi_device *dev, uint32_t addr,
+ void *val, size_t size);
+extern int fsi_device_write(struct fsi_device *dev, uint32_t addr,
+ const void *val, size_t size);
+extern int fsi_device_peek(struct fsi_device *dev, void *val);
+
struct fsi_device_id {
u8 engine_type;
u8 version;
@@ -40,7 +46,6 @@ struct fsi_device_id {
#define FSI_DEVICE_VERSIONED(t, v) \
.engine_type = (t), .version = (v),
-
struct fsi_driver {
struct device_driver drv;
const struct fsi_device_id *id_table;
--
1.8.2.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 12/16] drivers/fsi: Set up links for slave communication
From: Chris Bostic @ 2016-12-07 2:09 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
sre-DgEjT+Ai2ygdnm+yROfE0A, mturquette-rdvid1DuHRBWk0Htik3J/w,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Chris Bostic, joel-U3u1mxZcP9KHXe+LvDLADg,
jk-mnsaURCQ41sdnm+yROfE0A, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
andrew-zrmu5oMJ5Fs, alistair-Y4h6yKqj69EXC2x5gXVKYQ,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r
In-Reply-To: <1481076574-54711-1-git-send-email-christopher.lee.bostic-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
From: Chris Bostic <cbostic-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Enable each link and send a break command in preparation
for scanning each link for slaves.
Signed-off-by: Chris Bostic <cbostic-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
drivers/fsi/fsi-core.c | 39 ++++++++++++++++++++++++++++++++++++---
drivers/fsi/fsi-master.h | 2 ++
2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 80feeb8..93de0f1 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -290,16 +290,49 @@ 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;
+ }
+ return 0;
}
int fsi_master_register(struct fsi_master *master)
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index cafb433..56aad0e 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
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH] arm: dts: rockchip: add qos node for rk3288
From: Elaine Zhang @ 2016-12-07 2:17 UTC (permalink / raw)
To: heiko-4mtYJXux2i+zQB+pC5nmwQ, wxt-TNX95d0MmH7DzftRWevZcw
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
huangtao-TNX95d0MmH7DzftRWevZcw, xxx-TNX95d0MmH7DzftRWevZcw,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Elaine Zhang
when pd power on/off, the qos regs need to save and restore.
Signed-off-by: Elaine Zhang <zhangqing-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
arch/arm/boot/dts/rk3288.dtsi | 84 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 4fad13368a7b..2628edc871fa 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -699,6 +699,76 @@
reg = <0xff720000 0x1000>;
};
+ qos_gpu_r: qos@ffaa0000 {
+ compatible = "syscon";
+ reg = <0xffaa0000 0x20>;
+ };
+
+ qos_gpu_w: qos@ffaa0080 {
+ compatible = "syscon";
+ reg = <0xffaa0080 0x20>;
+ };
+
+ qos_vio1_vop: qos@ffad0000 {
+ compatible = "syscon";
+ reg = <0xffad0000 0x20>;
+ };
+
+ qos_vio1_isp_w0: qos@ffad0100 {
+ compatible = "syscon";
+ reg = <0xffad0100 0x20>;
+ };
+
+ qos_vio1_isp_w1: qos@ffad0180 {
+ compatible = "syscon";
+ reg = <0xffad0180 0x20>;
+ };
+
+ qos_vio0_vop: qos@ffad0400 {
+ compatible = "syscon";
+ reg = <0xffad0400 0x20>;
+ };
+
+ qos_vio0_vip: qos@ffad0480 {
+ compatible = "syscon";
+ reg = <0xffad0480 0x20>;
+ };
+
+ qos_vio0_iep: qos@ffad0500 {
+ compatible = "syscon";
+ reg = <0xffad0500 0x20>;
+ };
+
+ qos_vio2_rga_r: qos@ffad0800 {
+ compatible = "syscon";
+ reg = <0xffad0800 0x20>;
+ };
+
+ qos_vio2_rga_w: qos@ffad0880 {
+ compatible = "syscon";
+ reg = <0xffad0880 0x20>;
+ };
+
+ qos_vio1_isp_r: qos@ffad0900 {
+ compatible = "syscon";
+ reg = <0xffad0900 0x20>;
+ };
+
+ qos_video: qos@ffae0000 {
+ compatible = "syscon";
+ reg = <0xffae0000 0x20>;
+ };
+
+ qos_hevc_r: qos@ffaf0000 {
+ compatible = "syscon";
+ reg = <0xffaf0000 0x20>;
+ };
+
+ qos_hevc_w: qos@ffaf0080 {
+ compatible = "syscon";
+ reg = <0xffaf0080 0x20>;
+ };
+
pmu: power-management@ff730000 {
compatible = "rockchip,rk3288-pmu", "syscon", "simple-mfd";
reg = <0xff730000 0x100>;
@@ -762,6 +832,15 @@
<&cru SCLK_ISP_JPE>,
<&cru SCLK_ISP>,
<&cru SCLK_RGA>;
+ pm_qos = <&qos_vio0_iep>,
+ <&qos_vio1_vop>,
+ <&qos_vio1_isp_w0>,
+ <&qos_vio1_isp_w1>,
+ <&qos_vio0_vop>,
+ <&qos_vio0_vip>,
+ <&qos_vio2_rga_r>,
+ <&qos_vio2_rga_w>,
+ <&qos_vio1_isp_r>;
};
/*
@@ -773,6 +852,8 @@
clocks = <&cru ACLK_HEVC>,
<&cru SCLK_HEVC_CABAC>,
<&cru SCLK_HEVC_CORE>;
+ pm_qos = <&qos_hevc_r>,
+ <&qos_hevc_w>;
};
/*
@@ -784,6 +865,7 @@
reg = <RK3288_PD_VIDEO>;
clocks = <&cru ACLK_VCODEC>,
<&cru HCLK_VCODEC>;
+ pm_qos = <&qos_video>;
};
/*
@@ -793,6 +875,8 @@
pd_gpu@RK3288_PD_GPU {
reg = <RK3288_PD_GPU>;
clocks = <&cru ACLK_GPU>;
+ pm_qos = <&qos_gpu_r>,
+ <&qos_gpu_w>;
};
};
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH] n900 device tree: cleanup
From: Sebastian Reichel @ 2016-12-07 3:10 UTC (permalink / raw)
To: Pavel Machek
Cc: pali.rohar, kernel list, linux-arm-kernel, linux-omap, tony,
khilman, aaro.koskinen, ivo.g.dimitrov.75, patrikbachan, serge,
bcousson, robh+dt, mark.rutland, devicetree
In-Reply-To: <20161011081243.GA24580@amd>
[-- Attachment #1: Type: text/plain, Size: 1084 bytes --]
Hi Tony,
It looks like this fell through the cracks. Apart from inconsistent
patch subject:
Reviewed-By: Sebastian Reichel <sre@kernel.org>
-- Sebastian
On Tue, Oct 11, 2016 at 10:12:43AM +0200, Pavel Machek wrote:
> Fix GPIO comment to be consistent with rest of file and add comment what
> tpa6130 is.
>
> Signed-off-by: Pavel Machek <pavel@ucw.cz>
>
> diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
> index bfffd6c..ca9fe8c 100644
> --- a/arch/arm/boot/dts/omap3-n900.dts
> +++ b/arch/arm/boot/dts/omap3-n900.dts
> @@ -47,7 +47,7 @@
> compatible = "gpio-leds";
> heartbeat {
> label = "debug::sleep";
> - gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>; /* gpio162 */
> + gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>; /* 162 */
> linux,default-trigger = "default-on";
> pinctrl-names = "default";
> pinctrl-0 = <&debug_leds>;
> @@ -637,6 +637,7 @@
> reg = <0x55>;
> };
>
> + /* Stereo headphone amplifier */
> tpa6130a2: tpa6130a2@60 {
> compatible = "ti,tpa6130a2";
> reg = <0x60>;
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox