From: Alan Tull <atull@opensource.altera.com>
To: linux-kernel@vger.kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jason Gunthorpe <jgunthorpe@obsidianresearch.com>,
Pantelis Antoniou <pantelis.antoniou@konsulko.com>,
Grant Likely <grant.likely@linaro.org>,
Rob Herring <robh+dt@kernel.org>,
devicetree@vger.kernel.org, Pavel Machek <pavel@denx.de>,
Mark Brown <broonie@kernel.org>,
Philip Balister <philip@balister.org>,
Alessandro Rubini <rubini@gnudd.com>,
Steffen Trumtrar <s.trumtrar@pengutronix.de>,
Jason Cooper <jason@lakedaemon.net>,
Kyle Teske <kyle.teske@ni.com>, Nicolas Pitre <nico@linaro.org>,
Felipe Balbi <balbi@ti.com>,
Mauro Carvalho Chehab <m.chehab@samsung.com>,
David Brown <davidb@codeaurora.org>,
Rob Landley <rob@landley.net>,
"David S. Miller" <davem@davemloft.net>,
Joe Perches <joe@perches.com>,
Cesar Eduardo Barros <cesarb@cesarb.net>,
Samuel Ortiz <sameo@linux.intel.com>,
Andrew Morton <akpm@linux-foundation.org>,
Michal Simek <monstr@monstr.eu>,
Michal Simek <michal.simek@xilinx.com>,
Alan Tull <delicious.quinoa@gmail.com>,
Dinh Nguyen <dinguyen@opensource.altera.com>,
Yves Vandervennet <yvanderv@opensource.altera.com>,
Alan Tull <atull@opensource.altera.com>
Subject: [RFC PATCH 1/3] fpga manager framework core
Date: Thu, 31 Jul 2014 16:59:02 -0500 [thread overview]
Message-ID: <1406843944-7780-2-git-send-email-atull@opensource.altera.com> (raw)
In-Reply-To: <1406843944-7780-1-git-send-email-atull@opensource.altera.com>
This core exports methods of doing operations on FPGAs.
EXPORT_SYMBOL_GPL(fpga_mgr_write);
Write FPGA given a buffer and count.
EXPORT_SYMBOL_GPL(fpga_mgr_firmware_write);
Request firmware and write that to a fpga
EXPORT_SYMBOL_GPL(fpga_mgr_status_get);
Get a status string, including failure information
EXPORT_SYMBOL_GPL(fpga_mgr_name);
Get name of FPGA manager
EXPORT_SYMBOL_GPL(register_fpga_manager);
EXPORT_SYMBOL_GPL(remove_fpga_manager);
Register/unregister low level fpga driver
All userspace interfaces are in separate files so that
they can be compiled out on production builds where
appropriate.
Signed-off-by: Alan Tull <atull@opensource.altera.com>
---
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/fpga/Kconfig | 13 ++
drivers/fpga/Makefile | 10 ++
drivers/fpga/fpga-mgr.c | 403 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fpga-mgr.h | 121 ++++++++++++++
6 files changed, 550 insertions(+)
create mode 100644 drivers/fpga/Kconfig
create mode 100644 drivers/fpga/Makefile
create mode 100644 drivers/fpga/fpga-mgr.c
create mode 100644 include/linux/fpga-mgr.h
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 0e87a34..b0cbbae 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -34,6 +34,8 @@ source "drivers/message/fusion/Kconfig"
source "drivers/firewire/Kconfig"
+source "drivers/fpga/Kconfig"
+
source "drivers/message/i2o/Kconfig"
source "drivers/macintosh/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index f98b50d..afdd2aa 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_RESET_CONTROLLER) += reset/
# default.
obj-y += tty/
obj-y += char/
+obj-$(CONFIG_FPGA) += fpga/
# gpu/ comes after char for AGP vs DRM startup
obj-y += gpu/
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
new file mode 100644
index 0000000..49293a3
--- /dev/null
+++ b/drivers/fpga/Kconfig
@@ -0,0 +1,13 @@
+#
+# FPGA framework configuration
+#
+
+menu "FPGA devices"
+
+config FPGA
+ tristate "FPGA Framework"
+ help
+ Say Y here if you want support for configuring FPGAs from the
+ kernel. The FPGA framework adds a FPGA manager class and FPGA
+ manager drivers.
+endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
new file mode 100644
index 0000000..c8a676f
--- /dev/null
+++ b/drivers/fpga/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the fpga framework and fpga manager drivers.
+#
+
+fpga-mgr-core-y += fpga-mgr.o
+
+# Core FPGA Manager Framework
+obj-$(CONFIG_FPGA) += fpga-mgr-core.o
+
+# FPGA Manager Drivers
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
new file mode 100644
index 0000000..0e2eba4
--- /dev/null
+++ b/drivers/fpga/fpga-mgr.c
@@ -0,0 +1,403 @@
+/*
+ * FPGA Manager Core
+ *
+ * Copyright (C) 2013-2014 Altera Corporation
+ *
+ * With code from the mailing list:
+ * Copyright (C) 2013 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/fpga-mgr.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+
+static DEFINE_IDA(fpga_mgr_ida);
+static int fpga_mgr_major;
+static struct class *fpga_mgr_class;
+
+#define FPGA_MAX_MINORS 256
+
+static DEFINE_MUTEX(fpga_manager_mutex);
+static LIST_HEAD(fpga_manager_list);
+
+/*
+ * Unlocked version of fpga_mgr_write function.
+ * Does not touch flags. So caller must grab the FPGA_MGR_BUSY bit
+ * and update the FPGA_MGR_FAIL bit.
+ */
+static int __fpga_mgr_write(struct fpga_manager *mgr, const char *buf,
+ size_t count)
+{
+ int ret;
+
+ if (mgr->mops->write_init) {
+ mgr->state = FPGA_MGR_WRITE_INIT;
+ ret = mgr->mops->write_init(mgr);
+ if (ret)
+ return ret;
+ }
+
+ mgr->state = FPGA_MGR_WRITE;
+ ret = mgr->mops->write(mgr, buf, count);
+ if (ret)
+ return ret;
+
+ if (mgr->mops->write_complete) {
+ mgr->state = FPGA_MGR_WRITE_COMPLETE;
+ ret = mgr->mops->write_complete(mgr);
+ if (ret)
+ return ret;
+ }
+
+ mgr->state = FPGA_MGR_WRITE_SUCCESS;
+
+ return 0;
+}
+
+int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count)
+{
+ int ret;
+
+ if (test_and_set_bit_lock(FPGA_MGR_BUSY, &mgr->flags))
+ return -EBUSY;
+
+ dev_info(mgr->dev, "writing buffer to %s\n", mgr->name);
+
+ ret = __fpga_mgr_write(mgr, buf, count);
+ if (ret)
+ set_bit(FPGA_MGR_FAIL, &mgr->flags);
+ else
+ clear_bit(FPGA_MGR_FAIL, &mgr->flags);
+
+ clear_bit_unlock(FPGA_MGR_BUSY, &mgr->flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_write);
+
+/*
+ * Grab lock, request firmware, and write out to the FPGA.
+ * Update the state before each step to provide info on what step
+ * failed if there is a failure.
+ */
+int fpga_mgr_firmware_write(struct fpga_manager *mgr, const char *path)
+{
+ const struct firmware *fw;
+ int ret;
+
+ if (test_and_set_bit_lock(FPGA_MGR_BUSY, &mgr->flags))
+ return -EBUSY;
+
+ dev_info(mgr->dev, "writing %s to %s\n", path, mgr->name);
+
+ mgr->state = FPGA_MGR_FIRMWARE_REQ;
+ ret = request_firmware(&fw, path, mgr->dev);
+ if (ret)
+ goto fw_write_fail;
+
+ ret = __fpga_mgr_write(mgr, fw->data, fw->size);
+ if (ret)
+ goto fw_write_fail;
+
+ clear_bit(FPGA_MGR_FAIL, &mgr->flags);
+ clear_bit_unlock(FPGA_MGR_BUSY, &mgr->flags);
+
+ return 0;
+
+fw_write_fail:
+ set_bit(FPGA_MGR_FAIL, &mgr->flags);
+ clear_bit_unlock(FPGA_MGR_BUSY, &mgr->flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_firmware_write);
+
+int fpga_mgr_status_get(struct fpga_manager *mgr, char *buf)
+{
+ if (!mgr || !mgr->mops || !mgr->mops->status)
+ return -ENODEV;
+
+ return mgr->mops->status(mgr, buf);
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_status_get);
+
+int fpga_mgr_name(struct fpga_manager *mgr, char *buf)
+{
+ if (!mgr)
+ return -ENODEV;
+
+ return sprintf(buf, "%s\n", mgr->name);
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_name);
+
+static int fpga_mgr_get_new_minor(struct fpga_manager *mgr, int request_nr)
+{
+ int nr, start;
+
+ /* check specified minor number */
+ if (request_nr >= FPGA_MAX_MINORS) {
+ dev_err(mgr->parent, "Out of device minors (%d)\n", request_nr);
+ return -ENODEV;
+ }
+
+ /*
+ * If request_nr == -1, dynamically allocate number.
+ * If request_nr >= 0, attempt to get specific number.
+ */
+ if (request_nr == -1)
+ start = 0;
+ else
+ start = request_nr;
+
+ nr = ida_simple_get(&fpga_mgr_ida, start, FPGA_MAX_MINORS, GFP_KERNEL);
+
+ /* return error code */
+ if (nr < 0)
+ return nr;
+
+ if ((request_nr != -1) && (request_nr != nr)) {
+ dev_err(mgr->parent,
+ "Could not get requested device minor (%d)\n", nr);
+ ida_simple_remove(&fpga_mgr_ida, nr);
+ return -ENODEV;
+ }
+
+ mgr->nr = nr;
+
+ return 0;
+}
+
+static void fpga_mgr_free_minor(int nr)
+{
+ ida_simple_remove(&fpga_mgr_ida, nr);
+}
+
+const char *state_str[] = {
+ "default",
+ "firmware_request",
+ "write_init",
+ "write",
+ "write_complete",
+ "write_success",
+ "read_init",
+ "read",
+ "read_complete",
+ "read_done",
+};
+
+/*
+ * Provide status as: [state] [fail] [busy] such as
+ * 'firmware_request fail' = failed to load firmware image from filesystem
+ * 'write fail' = failed while writing to FPGA
+ * 'write_success' = after writing, low level driver returns success
+ */
+static int fpga_mgr_ops_framework_status(struct fpga_manager *mgr, char *buf)
+{
+ int ret = 0, flags = mgr->flags;
+
+ ret += sprintf(buf + ret, state_str[mgr->state]);
+
+ if (flags & BIT(FPGA_MGR_FAIL))
+ ret += sprintf(buf + ret, " fail");
+
+ if (flags & BIT(FPGA_MGR_BUSY))
+ ret += sprintf(buf + ret, " busy");
+
+ ret += sprintf(buf + ret, "\n");
+
+ return ret;
+}
+
+static int fpga_mgr_suspend(struct device *dev)
+{
+ struct fpga_manager *mgr = dev_get_drvdata(dev);
+
+ if (!mgr)
+ return -ENODEV;
+
+ if (mgr->mops->suspend)
+ return mgr->mops->suspend(mgr);
+
+ return 0;
+}
+
+static int fpga_mgr_resume(struct device *dev)
+{
+ struct fpga_manager *mgr = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (!mgr)
+ return -ENODEV;
+
+ if (mgr->mops->resume) {
+ ret = mgr->mops->resume(mgr);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+const struct dev_pm_ops fpga_mgr_dev_pm_ops = {
+ .suspend = fpga_mgr_suspend,
+ .resume = fpga_mgr_resume,
+};
+
+int register_fpga_manager(struct platform_device *pdev,
+ struct fpga_manager_ops *mops,
+ const char *name,
+ unsigned int num_areas,
+ void *priv)
+{
+ struct fpga_manager *mgr;
+ int ret;
+
+ BUG_ON(!mops || !name || !strlen(name));
+
+ mgr = devm_kzalloc(&pdev->dev, sizeof(struct fpga_manager), GFP_KERNEL);
+ if (!mgr)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, mgr);
+ mgr->mops = mops;
+
+ /* implementing status() for each fpga manager is optional */
+ if (!mgr->mops->status)
+ mgr->mops->status = fpga_mgr_ops_framework_status;
+
+ mgr->np = pdev->dev.of_node;
+ mgr->parent = get_device(&pdev->dev);
+ mgr->priv = priv;
+ mgr->name = name;
+ mgr->num_areas = num_areas;
+ init_completion(&mgr->status_complete);
+
+ ret = fpga_mgr_get_new_minor(mgr, pdev->id);
+ if (ret)
+ goto error_kfree;
+
+ if (mops->isr) {
+ mgr->irq = irq_of_parse_and_map(mgr->np, 0);
+ if (mgr->irq == NO_IRQ) {
+ dev_err(mgr->parent, "failed to map interrupt\n");
+ goto error_irq_map;
+ }
+
+ ret = request_irq(mgr->irq, mops->isr, 0, "fpga-mgr", mgr);
+ if (ret < 0) {
+ dev_err(mgr->parent, "error requesting interrupt\n");
+ goto error_irq_req;
+ }
+ }
+
+ mgr->dev = device_create(fpga_mgr_class, mgr->parent, MKDEV(0, 0), mgr,
+ "fpga%d", mgr->nr);
+ if (IS_ERR(mgr->dev)) {
+ ret = PTR_ERR(mgr->dev);
+ goto error_device;
+ }
+
+ fpga_mgr_class->pm = &fpga_mgr_dev_pm_ops;
+
+ dev_info(mgr->parent, "fpga manager [%s] registered as minor %d\n",
+ mgr->name, mgr->nr);
+
+ INIT_LIST_HEAD(&mgr->list);
+ mutex_lock(&fpga_manager_mutex);
+ list_add(&mgr->list, &fpga_manager_list);
+ mutex_unlock(&fpga_manager_mutex);
+
+ return 0;
+
+error_device:
+ cdev_del(&mgr->cdev);
+ free_irq(mgr->irq, mgr);
+error_irq_req:
+ irq_dispose_mapping(mgr->irq);
+error_irq_map:
+ fpga_mgr_free_minor(mgr->nr);
+error_kfree:
+ put_device(mgr->parent);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(register_fpga_manager);
+
+void remove_fpga_manager(struct platform_device *pdev)
+{
+ struct fpga_manager *mgr = platform_get_drvdata(pdev);
+
+ if (!mgr)
+ return;
+
+ if (mgr->mops->fpga_remove)
+ mgr->mops->fpga_remove(mgr);
+
+ mutex_lock(&fpga_manager_mutex);
+ list_del(&mgr->list);
+ mutex_unlock(&fpga_manager_mutex);
+
+ device_destroy(fpga_mgr_class, MKDEV(fpga_mgr_major, mgr->nr));
+ cdev_del(&mgr->cdev);
+ free_irq(mgr->irq, mgr);
+ irq_dispose_mapping(mgr->irq);
+ fpga_mgr_free_minor(mgr->nr);
+ put_device(mgr->parent);
+}
+EXPORT_SYMBOL_GPL(remove_fpga_manager);
+
+static int __init fpga_mgr_dev_init(void)
+{
+ dev_t fpga_mgr_dev;
+ int ret;
+
+ pr_info("FPGA Manager framework driver\n");
+
+ fpga_mgr_class = class_create(THIS_MODULE, "fpga_manager");
+ if (IS_ERR(fpga_mgr_class))
+ return PTR_ERR(fpga_mgr_class);
+
+ ret = alloc_chrdev_region(&fpga_mgr_dev, 0, FPGA_MAX_MINORS,
+ "fpga_manager");
+ if (ret) {
+ class_destroy(fpga_mgr_class);
+ return ret;
+ }
+
+ fpga_mgr_major = MAJOR(fpga_mgr_dev);
+
+ return 0;
+}
+
+static void __exit fpga_mgr_dev_exit(void)
+{
+ unregister_chrdev_region(MKDEV(fpga_mgr_major, 0), FPGA_MAX_MINORS);
+ class_destroy(fpga_mgr_class);
+ ida_destroy(&fpga_mgr_ida);
+}
+
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_DESCRIPTION("FPGA Manager framework driver");
+MODULE_LICENSE("GPL v2");
+
+subsys_initcall(fpga_mgr_dev_init);
+module_exit(fpga_mgr_dev_exit);
diff --git a/include/linux/fpga-mgr.h b/include/linux/fpga-mgr.h
new file mode 100644
index 0000000..6af0873
--- /dev/null
+++ b/include/linux/fpga-mgr.h
@@ -0,0 +1,121 @@
+/*
+ * FPGA Framework
+ *
+ * Copyright (C) 2013-2014 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/configfs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/cdev.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+
+#ifndef _LINUX_FPGA_MGR_H
+#define _LINUX_FPGA_MGR_H
+
+struct fpga_manager;
+
+/*
+ * fpga_manager_ops are the low level functions implemented by a specific
+ * fpga manager driver. Leaving any of these out that aren't needed is fine
+ * as they are all tested for NULL before being called.
+ */
+struct fpga_manager_ops {
+ /* Returns a string of the FPGA's status */
+ int (*status)(struct fpga_manager *mgr, char *buf);
+
+ /* Prepare the FPGA for reading its confuration data */
+ int (*read_init)(struct fpga_manager *mgr);
+
+ /* Read count bytes configuration data from the FPGA */
+ ssize_t (*read)(struct fpga_manager *mgr, char *buf, size_t count);
+
+ /* Return FPGA to a default state after reading is done */
+ int (*read_complete)(struct fpga_manager *mgr);
+
+ /* Prepare the FPGA to receive confuration data */
+ int (*write_init)(struct fpga_manager *mgr);
+
+ /* Write count bytes of configuration data to the FPGA */
+ int (*write)(struct fpga_manager *mgr, const char *buf, size_t count);
+
+ /* Return FPGA to default state after writing is done */
+ int (*write_complete)(struct fpga_manager *mgr);
+
+ /* Optional: Set FPGA into a specific state during driver remove */
+ void (*fpga_remove)(struct fpga_manager *mgr);
+
+ int (*suspend)(struct fpga_manager *mgr);
+
+ int (*resume)(struct fpga_manager *mgr);
+
+ /* FPGA mangager isr */
+ irqreturn_t (*isr)(int irq, void *dev_id);
+};
+
+/* flag bits */
+#define FPGA_MGR_BUSY 0
+#define FPGA_MGR_FAIL 1
+
+/* States */
+enum fpga_mgr_states {
+ FPGA_MGR_DEFAULT,
+ FPGA_MGR_FIRMWARE_REQ,
+ FPGA_MGR_WRITE_INIT,
+ FPGA_MGR_WRITE,
+ FPGA_MGR_WRITE_COMPLETE,
+ FPGA_MGR_WRITE_SUCCESS,
+ FPGA_MGR_READ_INIT,
+ FPGA_MGR_READ,
+ FPGA_MGR_READ_COMPLETE,
+ FPGA_MGR_READ_DONE,
+};
+
+struct fpga_manager {
+ const char *name;
+ int nr;
+ struct device_node *np;
+ struct device *parent;
+ struct device *dev;
+ struct cdev cdev;
+ struct configfs_subsystem configfs;
+
+ struct list_head list;
+
+ int irq;
+ struct completion status_complete;
+ unsigned long flags;
+ enum fpga_mgr_states state;
+ struct fpga_manager_ops *mops;
+ void *priv;
+};
+
+#if IS_ENABLED(CONFIG_FPGA)
+
+int fpga_mgr_firmware_write(struct fpga_manager *mgr, const char *path);
+int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count);
+int fpga_mgr_status_get(struct fpga_manager *mgr, char *buf);
+int fpga_mgr_name(struct fpga_manager *mgr, char *buf);
+
+int register_fpga_manager(struct platform_device *pdev,
+ struct fpga_manager_ops *mops,
+ const char *name,
+ void *priv);
+
+void remove_fpga_manager(struct platform_device *pdev);
+
+#endif /* CONFIG_FPGA */
+#endif /*_LINUX_FPGA_MGR_H */
--
1.7.9.5
next prev parent reply other threads:[~2014-07-31 21:59 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-31 21:59 [RFC PATCH 0/3] Yet another stab at a fpga framework Alan Tull
2014-07-31 21:59 ` Alan Tull [this message]
2014-08-08 21:16 ` [RFC PATCH 1/3] fpga manager framework core Rob Herring
2014-08-12 19:17 ` Alan Tull
2014-08-12 22:01 ` Rob Herring
2014-07-31 21:59 ` [RFC PATCH 2/3] fpga bus driver Alan Tull
2014-07-31 21:59 ` [RFC PATCH 3/3] fpga sysfs interface Alan Tull
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1406843944-7780-2-git-send-email-atull@opensource.altera.com \
--to=atull@opensource.altera.com \
--cc=akpm@linux-foundation.org \
--cc=balbi@ti.com \
--cc=broonie@kernel.org \
--cc=cesarb@cesarb.net \
--cc=davem@davemloft.net \
--cc=davidb@codeaurora.org \
--cc=delicious.quinoa@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=dinguyen@opensource.altera.com \
--cc=grant.likely@linaro.org \
--cc=gregkh@linuxfoundation.org \
--cc=hpa@zytor.com \
--cc=jason@lakedaemon.net \
--cc=jgunthorpe@obsidianresearch.com \
--cc=joe@perches.com \
--cc=kyle.teske@ni.com \
--cc=linux-kernel@vger.kernel.org \
--cc=m.chehab@samsung.com \
--cc=michal.simek@xilinx.com \
--cc=monstr@monstr.eu \
--cc=nico@linaro.org \
--cc=pantelis.antoniou@konsulko.com \
--cc=pavel@denx.de \
--cc=philip@balister.org \
--cc=rob@landley.net \
--cc=robh+dt@kernel.org \
--cc=rubini@gnudd.com \
--cc=s.trumtrar@pengutronix.de \
--cc=sameo@linux.intel.com \
--cc=yvanderv@opensource.altera.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).