* [PATCH v5 05/20] firmware: arm_scmi: add scmi protocol bus to enumerate protocol devices
From: Sudeep Holla @ 2018-01-02 14:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514904162-11201-1-git-send-email-sudeep.holla@arm.com>
The SCMI specification encompasses various protocols. However, not every
protocol has to be present on a given platform/implementation as not
every protocol is relevant for it.
Furthermore, the platform chooses which protocols it exposes to a given
agent. The only protocol that must be implemented is the base protocol.
The base protocol is used by an agent to discover which protocols are
available to it.
In order to enumerate the discovered implemented protocols, this patch
adds support for a separate scmi protocol bus. It also adds mechanism to
register support for different protocols.
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_scmi/Makefile | 3 +-
drivers/firmware/arm_scmi/bus.c | 232 +++++++++++++++++++++++++++++++++++++
drivers/firmware/arm_scmi/common.h | 1 +
include/linux/scmi_protocol.h | 62 ++++++++++
4 files changed, 297 insertions(+), 1 deletion(-)
create mode 100644 drivers/firmware/arm_scmi/bus.c
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index 5d9c7ef35f0f..5f4ec2613db6 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,3 +1,4 @@
-obj-y = scmi-driver.o scmi-protocols.o
+obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o
+scmi-bus-y = bus.o
scmi-driver-y = driver.o
scmi-protocols-y = base.o
diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
new file mode 100644
index 000000000000..cf1c2464cb0f
--- /dev/null
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -0,0 +1,232 @@
+/*
+ * System Control and Management Interface (SCMI) Message Protocol bus layer
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * 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/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+#include "common.h"
+
+static DEFINE_IDA(scmi_bus_id);
+static DEFINE_IDR(scmi_protocols);
+static DEFINE_SPINLOCK(protocol_lock);
+
+static const struct scmi_device_id *
+scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv)
+{
+ const struct scmi_device_id *id = scmi_drv->id_table;
+
+ if (!id)
+ return NULL;
+
+ for (; id->protocol_id; id++)
+ if (id->protocol_id == scmi_dev->protocol_id)
+ return id;
+
+ return NULL;
+}
+
+static int scmi_dev_match(struct device *dev, struct device_driver *drv)
+{
+ struct scmi_driver *scmi_drv = to_scmi_driver(drv);
+ struct scmi_device *scmi_dev = to_scmi_dev(dev);
+ const struct scmi_device_id *id;
+
+ id = scmi_dev_match_id(scmi_dev, scmi_drv);
+ if (id)
+ return 1;
+
+ return 0;
+}
+
+static int scmi_protocol_init(int protocol_id, struct scmi_handle *handle)
+{
+ scmi_prot_init_fn_t fn = idr_find(&scmi_protocols, protocol_id);
+
+ if (unlikely(!fn))
+ return -EINVAL;
+ return fn(handle);
+}
+
+static int scmi_dev_probe(struct device *dev)
+{
+ struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
+ struct scmi_device *scmi_dev = to_scmi_dev(dev);
+ const struct scmi_device_id *id;
+ int ret;
+
+ id = scmi_dev_match_id(scmi_dev, scmi_drv);
+ if (!id)
+ return -ENODEV;
+
+ if (!scmi_dev->handle)
+ return -EPROBE_DEFER;
+
+ ret = scmi_protocol_init(scmi_dev->protocol_id, scmi_dev->handle);
+ if (ret)
+ return ret;
+
+ return scmi_drv->probe(scmi_dev);
+}
+
+static int scmi_dev_remove(struct device *dev)
+{
+ struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
+ struct scmi_device *scmi_dev = to_scmi_dev(dev);
+
+ if (scmi_drv->remove)
+ scmi_drv->remove(scmi_dev);
+
+ return 0;
+}
+
+static struct bus_type scmi_bus_type = {
+ .name = "scmi_protocol",
+ .match = scmi_dev_match,
+ .probe = scmi_dev_probe,
+ .remove = scmi_dev_remove,
+};
+
+int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
+ const char *mod_name)
+{
+ int retval;
+
+ driver->driver.bus = &scmi_bus_type;
+ driver->driver.name = driver->name;
+ driver->driver.owner = owner;
+ driver->driver.mod_name = mod_name;
+
+ retval = driver_register(&driver->driver);
+ if (!retval)
+ pr_debug("registered new scmi driver %s\n", driver->name);
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(scmi_driver_register);
+
+void scmi_driver_unregister(struct scmi_driver *driver)
+{
+ driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(scmi_driver_unregister);
+
+struct scmi_device *
+scmi_device_create(struct device_node *np, struct device *parent, int protocol)
+{
+ int id, retval;
+ struct scmi_device *scmi_dev;
+
+ id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
+ if (id < 0)
+ return NULL;
+
+ scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL);
+ if (!scmi_dev)
+ goto no_mem;
+
+ scmi_dev->id = id;
+ scmi_dev->protocol_id = protocol;
+ scmi_dev->dev.parent = parent;
+ scmi_dev->dev.of_node = np;
+ scmi_dev->dev.bus = &scmi_bus_type;
+ dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
+
+ retval = device_register(&scmi_dev->dev);
+ if (!retval)
+ return scmi_dev;
+
+ put_device(&scmi_dev->dev);
+ kfree(scmi_dev);
+no_mem:
+ ida_simple_remove(&scmi_bus_id, id);
+ return NULL;
+}
+
+void scmi_device_destroy(struct scmi_device *scmi_dev)
+{
+ scmi_handle_put(scmi_dev->handle);
+ device_unregister(&scmi_dev->dev);
+ ida_simple_remove(&scmi_bus_id, scmi_dev->id);
+ kfree(scmi_dev);
+}
+
+void scmi_set_handle(struct scmi_device *scmi_dev)
+{
+ scmi_dev->handle = scmi_handle_get(&scmi_dev->dev);
+}
+
+int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn)
+{
+ int ret;
+
+ spin_lock(&protocol_lock);
+ ret = idr_alloc(&scmi_protocols, fn, protocol_id, protocol_id + 1,
+ GFP_KERNEL);
+ if (ret != protocol_id)
+ pr_err("unable to allocate SCMI idr slot, err %d\n", ret);
+ spin_unlock(&protocol_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(scmi_protocol_register);
+
+void scmi_protocol_unregister(int protocol_id)
+{
+ spin_lock(&protocol_lock);
+ idr_remove(&scmi_protocols, protocol_id);
+ spin_unlock(&protocol_lock);
+}
+EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
+
+static int __scmi_devices_unregister(struct device *dev, void *data)
+{
+ struct scmi_device *scmi_dev = to_scmi_dev(dev);
+
+ scmi_device_destroy(scmi_dev);
+ return 0;
+}
+
+static void scmi_devices_unregister(void)
+{
+ bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
+}
+
+static int __init scmi_bus_init(void)
+{
+ int retval;
+
+ retval = bus_register(&scmi_bus_type);
+ if (retval)
+ pr_err("scmi protocol bus register failed (%d)\n", retval);
+
+ return retval;
+}
+subsys_initcall(scmi_bus_init);
+
+static void __exit scmi_bus_exit(void)
+{
+ scmi_devices_unregister();
+ bus_unregister(&scmi_bus_type);
+ ida_destroy(&scmi_bus_id);
+}
+module_exit(scmi_bus_exit);
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index bc767f4997e0..f1eeacaef57b 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -107,6 +107,7 @@ int scmi_one_xfer_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
size_t tx_size, size_t rx_size, struct scmi_xfer **p);
int scmi_handle_put(const struct scmi_handle *handle);
struct scmi_handle *scmi_handle_get(struct device *dev);
+void scmi_set_handle(struct scmi_device *scmi_dev);
int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version);
void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
u8 *prot_imp);
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 664da3d763f2..7b72c75cb560 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -15,6 +15,7 @@
* 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/device.h>
#include <linux/types.h>
#define SCMI_MAX_STR_SIZE 16
@@ -62,3 +63,64 @@ enum scmi_std_protocol {
SCMI_PROTOCOL_CLOCK = 0x14,
SCMI_PROTOCOL_SENSOR = 0x15,
};
+
+struct scmi_device {
+ u32 id;
+ u8 protocol_id;
+ struct device dev;
+ struct scmi_handle *handle;
+};
+
+#define to_scmi_dev(d) container_of(d, struct scmi_device, dev)
+
+struct scmi_device *
+scmi_device_create(struct device_node *np, struct device *parent, int protocol);
+void scmi_device_destroy(struct scmi_device *scmi_dev);
+
+struct scmi_device_id {
+ u8 protocol_id;
+};
+
+struct scmi_driver {
+ const char *name;
+ int (*probe)(struct scmi_device *);
+ void (*remove)(struct scmi_device *);
+ const struct scmi_device_id *id_table;
+
+ struct device_driver driver;
+};
+
+#define to_scmi_driver(d) container_of(d, struct scmi_driver, driver)
+
+#ifdef CONFIG_ARM_SCMI_PROTOCOL
+int scmi_driver_register(struct scmi_driver *driver,
+ struct module *owner, const char *mod_name);
+void scmi_driver_unregister(struct scmi_driver *driver);
+#else
+static int scmi_driver_register(struct scmi_driver *driver,
+ struct module *owner, const char *mod_name)
+{
+ return -EINVAL;
+}
+static void scmi_driver_unregister(struct scmi_driver *driver) {}
+#endif /* CONFIG_ARM_SCMI_PROTOCOL */
+
+#define scmi_register(driver) \
+ scmi_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
+#define scmi_unregister(driver) \
+ scmi_driver_unregister(driver)
+
+/**
+ * module_scmi_driver() - Helper macro for registering a scmi driver
+ * @__scmi_driver: scmi_driver structure
+ *
+ * Helper macro for scmi drivers to set up proper module init / exit
+ * functions. Replaces module_init() and module_exit() and keeps people from
+ * printing pointless things to the kernel log when their driver is loaded.
+ */
+#define module_scmi_driver(__scmi_driver) \
+ module_driver(__scmi_driver, scmi_register, scmi_unregister)
+
+typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *);
+int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn);
+void scmi_protocol_unregister(int protocol_id);
--
2.7.4
^ permalink raw reply related
* [PATCH v5 04/20] firmware: arm_scmi: add common infrastructure and support for base protocol
From: Sudeep Holla @ 2018-01-02 14:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514904162-11201-1-git-send-email-sudeep.holla@arm.com>
The base protocol describes the properties of the implementation and
provide generic error management. The base protocol provides commands
to describe protocol version, discover implementation specific
attributes and vendor/sub-vendor identification, list of protocols
implemented and the various agents are in the system including OSPM
and the platform. It also supports registering for notifications of
platform errors.
This protocol is mandatory. This patch adds support for the same along
with some basic infrastructure to add support for other protocols.
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_scmi/Makefile | 3 +-
drivers/firmware/arm_scmi/base.c | 293 +++++++++++++++++++++++++++++++++++++
drivers/firmware/arm_scmi/common.h | 37 +++++
drivers/firmware/arm_scmi/driver.c | 53 +++++++
include/linux/scmi_protocol.h | 37 +++++
5 files changed, 422 insertions(+), 1 deletion(-)
create mode 100644 drivers/firmware/arm_scmi/base.c
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
index b2a24ba2b636..5d9c7ef35f0f 100644
--- a/drivers/firmware/arm_scmi/Makefile
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -1,2 +1,3 @@
-obj-y = scmi-driver.o
+obj-y = scmi-driver.o scmi-protocols.o
scmi-driver-y = driver.o
+scmi-protocols-y = base.o
diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
new file mode 100644
index 000000000000..2b5fbb724899
--- /dev/null
+++ b/drivers/firmware/arm_scmi/base.c
@@ -0,0 +1,293 @@
+/*
+ * System Control and Management Interface (SCMI) Base Protocol
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * 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 "common.h"
+
+enum scmi_base_protocol_cmd {
+ BASE_DISCOVER_VENDOR = 0x3,
+ BASE_DISCOVER_SUB_VENDOR = 0x4,
+ BASE_DISCOVER_IMPLEMENT_VERSION = 0x5,
+ BASE_DISCOVER_LIST_PROTOCOLS = 0x6,
+ BASE_DISCOVER_AGENT = 0x7,
+ BASE_NOTIFY_ERRORS = 0x8,
+};
+
+struct scmi_msg_resp_base_attributes {
+ u8 num_protocols;
+ u8 num_agents;
+ __le16 reserved;
+};
+
+/**
+ * scmi_base_attributes_get() - gets the implementation details
+ * that are associated with the base protocol.
+ *
+ * @handle - SCMI entity handle
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_attributes_get(const struct scmi_handle *handle)
+{
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_resp_base_attributes *attr_info;
+ struct scmi_revision_info *rev = handle->version;
+
+ ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+ SCMI_PROTOCOL_BASE, 0, sizeof(*attr_info), &t);
+ if (ret)
+ return ret;
+
+ ret = scmi_do_xfer(handle, t);
+ if (!ret) {
+ attr_info = t->rx.buf;
+ rev->num_protocols = attr_info->num_protocols;
+ rev->num_agents = attr_info->num_agents;
+ }
+
+ scmi_one_xfer_put(handle, t);
+ return ret;
+}
+
+/**
+ * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
+ *
+ * @handle - SCMI entity handle
+ * @sub_vendor - specify true if sub-vendor ID is needed
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
+{
+ u8 cmd;
+ int ret, size;
+ char *vendor_id;
+ struct scmi_xfer *t;
+ struct scmi_revision_info *rev = handle->version;
+
+ if (sub_vendor) {
+ cmd = BASE_DISCOVER_SUB_VENDOR;
+ vendor_id = rev->sub_vendor_id;
+ size = ARRAY_SIZE(rev->sub_vendor_id);
+ } else {
+ cmd = BASE_DISCOVER_VENDOR;
+ vendor_id = rev->vendor_id;
+ size = ARRAY_SIZE(rev->vendor_id);
+ }
+
+ ret = scmi_one_xfer_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t);
+ if (ret)
+ return ret;
+
+ ret = scmi_do_xfer(handle, t);
+ if (!ret)
+ memcpy(vendor_id, t->rx.buf, size);
+
+ scmi_one_xfer_put(handle, t);
+ return ret;
+}
+
+/**
+ * scmi_base_implementation_version_get() - gets a vendor-specific
+ * implementation 32-bit version. The format of the version number is
+ * vendor-specific
+ *
+ * @handle - SCMI entity handle
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_implementation_version_get(const struct scmi_handle *handle)
+{
+ int ret;
+ __le32 *impl_ver;
+ struct scmi_xfer *t;
+ struct scmi_revision_info *rev = handle->version;
+
+ ret = scmi_one_xfer_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION,
+ SCMI_PROTOCOL_BASE, 0, sizeof(*impl_ver), &t);
+ if (ret)
+ return ret;
+
+ ret = scmi_do_xfer(handle, t);
+ if (!ret) {
+ impl_ver = t->rx.buf;
+ rev->impl_ver = le32_to_cpu(*impl_ver);
+ }
+
+ scmi_one_xfer_put(handle, t);
+ return ret;
+}
+
+/**
+ * scmi_base_implementation_list_get() - gets the list of protocols it is
+ * OSPM is allowed to access
+ *
+ * @handle - SCMI entity handle
+ * @protocols_imp - pointer to hold the list of protocol identifiers
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
+ u8 *protocols_imp)
+{
+ u8 *list;
+ int ret, loop;
+ struct scmi_xfer *t;
+ __le32 *num_skip, *num_ret;
+ u32 tot_num_ret = 0, loop_num_ret;
+ struct device *dev = handle->dev;
+
+ ret = scmi_one_xfer_init(handle, BASE_DISCOVER_LIST_PROTOCOLS,
+ SCMI_PROTOCOL_BASE, sizeof(*num_skip), 0, &t);
+ if (ret)
+ return ret;
+
+ num_skip = t->tx.buf;
+ num_ret = t->rx.buf;
+ list = t->rx.buf + sizeof(*num_ret);
+
+ do {
+ /* Set the number of protocols to be skipped/already read */
+ *num_skip = cpu_to_le32(tot_num_ret);
+
+ ret = scmi_do_xfer(handle, t);
+ if (ret)
+ break;
+
+ loop_num_ret = le32_to_cpu(*num_ret);
+ if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) {
+ dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP");
+ break;
+ }
+
+ for (loop = 0; loop < loop_num_ret; loop++)
+ protocols_imp[tot_num_ret + loop] = *(list + loop);
+
+ tot_num_ret += loop_num_ret;
+ } while (loop_num_ret);
+
+ scmi_one_xfer_put(handle, t);
+ return ret;
+}
+
+/**
+ * scmi_base_discover_agent_get() - discover the name of an agent
+ *
+ * @handle - SCMI entity handle
+ * @id - Agent identifier
+ * @name - Agent identifier ASCII string
+ *
+ * An agent id of 0 is reserved to identify the platform itself.
+ * Generally operating system is represented as "OSPM"
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
+ int id, char *name)
+{
+ int ret;
+ struct scmi_xfer *t;
+
+ ret = scmi_one_xfer_init(handle, BASE_DISCOVER_AGENT,
+ SCMI_PROTOCOL_BASE, sizeof(__le32),
+ SCMI_MAX_STR_SIZE, &t);
+ if (ret)
+ return ret;
+
+ *(__le32 *)t->tx.buf = cpu_to_le32(id);
+
+ ret = scmi_do_xfer(handle, t);
+ if (!ret)
+ memcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE);
+
+ scmi_one_xfer_put(handle, t);
+ return ret;
+}
+
+/**
+ * scmi_base_error_notifications_enable() - register/unregister for
+ * notifications of errors in the platform
+ *
+ * @handle - SCMI entity handle
+ * @enable - Enable/Disable the notification
+ *
+ * Return: 0 on success, else appropriate SCMI error.
+ */
+static int
+scmi_base_error_notifications_enable(const struct scmi_handle *handle, bool en)
+{
+ int ret;
+ struct scmi_xfer *t;
+
+ ret = scmi_one_xfer_init(handle, BASE_NOTIFY_ERRORS, SCMI_PROTOCOL_BASE,
+ sizeof(__le32), 0, &t);
+ if (ret)
+ return ret;
+
+ *(__le32 *)t->tx.buf = cpu_to_le32(en & BIT(0));
+
+ ret = scmi_do_xfer(handle, t);
+
+ scmi_one_xfer_put(handle, t);
+ return ret;
+}
+
+int scmi_base_protocol_init(struct scmi_handle *h)
+{
+ int id, ret;
+ u8 *prot_imp;
+ u32 version;
+ char name[SCMI_MAX_STR_SIZE];
+ const struct scmi_handle *handle = h;
+ struct device *dev = handle->dev;
+ struct scmi_revision_info *rev = handle->version;
+
+ ret = scmi_version_get(handle, SCMI_PROTOCOL_BASE, &version);
+ if (ret)
+ return ret;
+
+ prot_imp = devm_kcalloc(dev, MAX_PROTOCOLS_IMP, sizeof(u8), GFP_KERNEL);
+ if (!prot_imp)
+ return -ENOMEM;
+
+ rev->major_ver = PROTOCOL_REV_MAJOR(version),
+ rev->minor_ver = PROTOCOL_REV_MINOR(version);
+
+ scmi_base_attributes_get(handle);
+ scmi_base_vendor_id_get(handle, false);
+ scmi_base_vendor_id_get(handle, true);
+ scmi_base_implementation_version_get(handle);
+ scmi_base_implementation_list_get(handle, prot_imp);
+ scmi_base_error_notifications_enable(handle, true);
+ scmi_setup_protocol_implemented(handle, prot_imp);
+
+ dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",
+ rev->major_ver, rev->minor_ver, rev->vendor_id,
+ rev->sub_vendor_id, rev->impl_ver);
+ dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols,
+ rev->num_agents);
+
+ for (id = 0; id < rev->num_agents; id++) {
+ scmi_base_discover_agent_get(handle, id, name);
+ dev_dbg(dev, "Agent %d: %s\n", id, name);
+ }
+
+ return 0;
+}
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index cdfc43427c3c..bc767f4997e0 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -19,9 +19,41 @@
*/
#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
#include <linux/scmi_protocol.h>
#include <linux/types.h>
+#define PROTOCOL_REV_MINOR_BITS 16
+#define PROTOCOL_REV_MINOR_MASK ((1U << PROTOCOL_REV_MINOR_BITS) - 1)
+#define PROTOCOL_REV_MAJOR(x) ((x) >> PROTOCOL_REV_MINOR_BITS)
+#define PROTOCOL_REV_MINOR(x) ((x) & PROTOCOL_REV_MINOR_MASK)
+#define MAX_PROTOCOLS_IMP 16
+
+enum scmi_common_cmd {
+ PROTOCOL_VERSION = 0x0,
+ PROTOCOL_ATTRIBUTES = 0x1,
+ PROTOCOL_MESSAGE_ATTRIBUTES = 0x2,
+};
+
+/**
+ * struct scmi_msg_resp_prot_version - Response for a message
+ *
+ * @major_version: Major version of the ABI that firmware supports
+ * @minor_version: Minor version of the ABI that firmware supports
+ *
+ * In general, ABI version changes follow the rule that minor version increments
+ * are backward compatible. Major revision changes in ABI may not be
+ * backward compatible.
+ *
+ * Response to a generic message with message type SCMI_MSG_VERSION
+ */
+struct scmi_msg_resp_prot_version {
+ __le16 minor_version;
+ __le16 major_version;
+};
+
/**
* struct scmi_msg_hdr - Message(Tx/Rx) header
*
@@ -75,3 +107,8 @@ int scmi_one_xfer_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
size_t tx_size, size_t rx_size, struct scmi_xfer **p);
int scmi_handle_put(const struct scmi_handle *handle);
struct scmi_handle *scmi_handle_get(struct device *dev);
+int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version);
+void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+ u8 *prot_imp);
+
+int scmi_base_protocol_init(struct scmi_handle *h);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 58d8f88893e6..20d083be474c 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -108,21 +108,27 @@ struct scmi_desc {
* @dev: Device pointer
* @desc: SoC description for this instance
* @handle: Instance of SCMI handle to send to clients
+ * @version: SCMI revision information containing protocol version,
+ * implementation version and (sub-)vendor identification.
* @cl: Mailbox Client
* @tx_chan: Transmit mailbox channel
* @tx_payload: Transmit mailbox channel payload area
* @minfo: Message info
+ * @protocols_imp: list of protocols implemented, currently maximum of
+ * MAX_PROTOCOLS_IMP elements allocated by the base protocol
* @node: list head
* @users: Number of users of this instance
*/
struct scmi_info {
struct device *dev;
const struct scmi_desc *desc;
+ struct scmi_revision_info version;
struct scmi_handle handle;
struct mbox_client cl;
struct mbox_chan *tx_chan;
void __iomem *tx_payload;
struct scmi_xfers_info minfo;
+ u8 *protocols_imp;
struct list_head node;
int users;
};
@@ -450,6 +456,45 @@ int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
}
/**
+ * scmi_version_get() - command to get the revision of the SCMI entity
+ *
+ * @handle: Handle to SCMI entity information
+ *
+ * Updates the SCMI information in the internal data structure.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+int scmi_version_get(const struct scmi_handle *handle, u8 protocol,
+ u32 *version)
+{
+ int ret;
+ __le32 *rev_info;
+ struct scmi_xfer *t;
+
+ ret = scmi_one_xfer_init(handle, PROTOCOL_VERSION, protocol, 0,
+ sizeof(*version), &t);
+ if (ret)
+ return ret;
+
+ ret = scmi_do_xfer(handle, t);
+ if (!ret) {
+ rev_info = t->rx.buf;
+ *version = le32_to_cpu(*rev_info);
+ }
+
+ scmi_one_xfer_put(handle, t);
+ return ret;
+}
+
+void scmi_setup_protocol_implemented(const struct scmi_handle *handle,
+ u8 *prot_imp)
+{
+ struct scmi_info *info = handle_to_scmi_info(handle);
+
+ info->protocols_imp = prot_imp;
+}
+
+/**
* scmi_handle_get() - Get the SCMI handle for a device
*
* @dev: pointer to device for which we want SCMI handle
@@ -679,11 +724,19 @@ static int scmi_probe(struct platform_device *pdev)
handle = &info->handle;
handle->dev = info->dev;
+ handle->version = &info->version;
ret = scmi_mbox_chan_setup(info);
if (ret)
return ret;
+ ret = scmi_base_protocol_init(handle);
+ if (ret) {
+ dev_err(dev, "unable to communicate with SCMI(%d)\n", ret);
+ scmi_mbox_free_channel(info);
+ return ret;
+ }
+
mutex_lock(&scmi_list_mutex);
list_add_tail(&info->node, &scmi_list);
mutex_unlock(&scmi_list_mutex);
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 854ed2479993..664da3d763f2 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -17,11 +17,48 @@
*/
#include <linux/types.h>
+#define SCMI_MAX_STR_SIZE 16
+
+/**
+ * struct scmi_revision_info - version information structure
+ *
+ * @major_ver: Major ABI version. Change here implies risk of backward
+ * compatibility break.
+ * @minor_ver: Minor ABI version. Change here implies new feature addition,
+ * or compatible change in ABI.
+ * @num_protocols: Number of protocols that are implemented, excluding the
+ * base protocol.
+ * @num_agents: Number of agents in the system.
+ * @impl_ver: A vendor-specific implementation version.
+ * @vendor_id: A vendor identifier(Null terminated ASCII string)
+ * @sub_vendor_id: A sub-vendor identifier(Null terminated ASCII string)
+ */
+struct scmi_revision_info {
+ u16 major_ver;
+ u16 minor_ver;
+ u8 num_protocols;
+ u8 num_agents;
+ u32 impl_ver;
+ char vendor_id[SCMI_MAX_STR_SIZE];
+ char sub_vendor_id[SCMI_MAX_STR_SIZE];
+};
+
/**
* struct scmi_handle - Handle returned to ARM SCMI clients for usage.
*
* @dev: pointer to the SCMI device
+ * @version: pointer to the structure containing SCMI version information
*/
struct scmi_handle {
struct device *dev;
+ struct scmi_revision_info *version;
+};
+
+enum scmi_std_protocol {
+ SCMI_PROTOCOL_BASE = 0x10,
+ SCMI_PROTOCOL_POWER = 0x11,
+ SCMI_PROTOCOL_SYSTEM = 0x12,
+ SCMI_PROTOCOL_PERF = 0x13,
+ SCMI_PROTOCOL_CLOCK = 0x14,
+ SCMI_PROTOCOL_SENSOR = 0x15,
};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 03/20] firmware: arm_scmi: add basic driver infrastructure for SCMI
From: Sudeep Holla @ 2018-01-02 14:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514904162-11201-1-git-send-email-sudeep.holla@arm.com>
The SCMI is intended to allow OSPM to manage various functions that are
provided by the hardware platform it is running on, including power and
performance functions. SCMI provides two levels of abstraction, protocols
and transports. Protocols define individual groups of system control and
management messages. A protocol specification describes the messages
that it supports. Transports describe the method by which protocol
messages are communicated between agents and the platform.
This patch adds basic infrastructure to manage the message allocation,
initialisation, packing/unpacking and shared memory management.
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
MAINTAINERS | 3 +-
drivers/firmware/Kconfig | 21 ++
drivers/firmware/Makefile | 1 +
drivers/firmware/arm_scmi/Makefile | 2 +
drivers/firmware/arm_scmi/common.h | 77 ++++
drivers/firmware/arm_scmi/driver.c | 708 +++++++++++++++++++++++++++++++++++++
include/linux/scmi_protocol.h | 27 ++
7 files changed, 838 insertions(+), 1 deletion(-)
create mode 100644 drivers/firmware/arm_scmi/Makefile
create mode 100644 drivers/firmware/arm_scmi/common.h
create mode 100644 drivers/firmware/arm_scmi/driver.c
create mode 100644 include/linux/scmi_protocol.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 56885de4ba44..e7526be3a05b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13157,7 +13157,8 @@ F: Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
F: drivers/clk/clk-scpi.c
F: drivers/cpufreq/scpi-cpufreq.c
F: drivers/firmware/arm_scpi.c
-F: include/linux/scpi_protocol.h
+F: drivers/firmware/arm_scmi/
+F: include/linux/sc[mp]i_protocol.h
SYSTEM RESET/SHUTDOWN DRIVERS
M: Sebastian Reichel <sre@kernel.org>
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index fa87a055905e..10b917d32087 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -19,6 +19,27 @@ config ARM_PSCI_CHECKER
on and off through hotplug, so for now torture tests and PSCI checker
are mutually exclusive.
+config ARM_SCMI_PROTOCOL
+ bool "ARM System Control and Management Interface (SCMI) Message Protocol"
+ depends on ARM || ARM64 || COMPILE_TEST
+ depends on MAILBOX
+ help
+ ARM System Control and Management Interface (SCMI) protocol is a
+ set of operating system-independent software interfaces that are
+ used in system management. SCMI is extensible and currently provides
+ interfaces for: Discovery and self-description of the interfaces
+ it supports, Power domain management which is the ability to place
+ a given device or domain into the various power-saving states that
+ it supports, Performance management which is the ability to control
+ the performance of a domain that is composed of compute engines
+ such as application processors and other accelerators, Clock
+ management which is the ability to set and inquire rates on platform
+ managed clocks and Sensor management which is the ability to read
+ sensor data, and be notified of sensor value.
+
+ This protocol library provides interface for all the client drivers
+ making use of the features offered by the SCMI.
+
config ARM_SCPI_PROTOCOL
tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
depends on ARM || ARM64 || COMPILE_TEST
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index feaa890197f3..33dcc099e021 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
+obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/
obj-y += broadcom/
obj-y += meson/
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile
new file mode 100644
index 000000000000..b2a24ba2b636
--- /dev/null
+++ b/drivers/firmware/arm_scmi/Makefile
@@ -0,0 +1,2 @@
+obj-y = scmi-driver.o
+scmi-driver-y = driver.o
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
new file mode 100644
index 000000000000..cdfc43427c3c
--- /dev/null
+++ b/drivers/firmware/arm_scmi/common.h
@@ -0,0 +1,77 @@
+/*
+ * System Control and Management Interface (SCMI) Message Protocol
+ * driver common header file containing some definitions, structures
+ * and function prototypes used in all the different SCMI protocols.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * 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/completion.h>
+#include <linux/scmi_protocol.h>
+#include <linux/types.h>
+
+/**
+ * struct scmi_msg_hdr - Message(Tx/Rx) header
+ *
+ * @id: The identifier of the command being sent
+ * @protocol_id: The identifier of the protocol used to send @id command
+ * @seq: The token to identify the message. when a message/command returns,
+ * the platform returns the whole message header unmodified including
+ * the token.
+ */
+struct scmi_msg_hdr {
+ u8 id;
+ u8 protocol_id;
+ u16 seq;
+ u32 status;
+ bool poll_completion;
+};
+
+/**
+ * struct scmi_msg - Message(Tx/Rx) structure
+ *
+ * @buf: Buffer pointer
+ * @len: Length of data in the Buffer
+ */
+struct scmi_msg {
+ void *buf;
+ size_t len;
+};
+
+/**
+ * struct scmi_xfer - Structure representing a message flow
+ *
+ * @hdr: Transmit message header
+ * @tx: Transmit message
+ * @rx: Receive message, the buffer should be pre-allocated to store
+ * message. If request-ACK protocol is used, we can reuse the same
+ * buffer for the rx path as we use for the tx path.
+ * @done: completion event
+ */
+
+struct scmi_xfer {
+ void *con_priv;
+ struct scmi_msg_hdr hdr;
+ struct scmi_msg tx;
+ struct scmi_msg rx;
+ struct completion done;
+};
+
+void scmi_one_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
+int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
+int scmi_one_xfer_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
+ size_t tx_size, size_t rx_size, struct scmi_xfer **p);
+int scmi_handle_put(const struct scmi_handle *handle);
+struct scmi_handle *scmi_handle_get(struct device *dev);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
new file mode 100644
index 000000000000..58d8f88893e6
--- /dev/null
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -0,0 +1,708 @@
+/*
+ * System Control and Management Interface (SCMI) Message Protocol driver
+ *
+ * SCMI Message Protocol is used between the System Control Processor(SCP)
+ * and the Application Processors(AP). The Message Handling Unit(MHU)
+ * provides a mechanism for inter-processor communication between SCP's
+ * Cortex M3 and AP.
+ *
+ * SCP offers control and management of the core/cluster power states,
+ * various power domain DVFS including the core/cluster, certain system
+ * clocks configuration, thermal sensors and many others.
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * 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/bitmap.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+
+#include "common.h"
+
+#define MSG_ID_SHIFT 0
+#define MSG_ID_MASK 0xff
+#define MSG_TYPE_SHIFT 8
+#define MSG_TYPE_MASK 0x3
+#define MSG_PROTOCOL_ID_SHIFT 10
+#define MSG_PROTOCOL_ID_MASK 0xff
+#define MSG_TOKEN_ID_SHIFT 18
+#define MSG_TOKEN_ID_MASK 0x3ff
+#define MSG_XTRACT_TOKEN(header) \
+ (((header) >> MSG_TOKEN_ID_SHIFT) & MSG_TOKEN_ID_MASK)
+
+enum scmi_error_codes {
+ SCMI_SUCCESS = 0, /* Success */
+ SCMI_ERR_SUPPORT = -1, /* Not supported */
+ SCMI_ERR_PARAMS = -2, /* Invalid Parameters */
+ SCMI_ERR_ACCESS = -3, /* Invalid access/permission denied */
+ SCMI_ERR_ENTRY = -4, /* Not found */
+ SCMI_ERR_RANGE = -5, /* Value out of range */
+ SCMI_ERR_BUSY = -6, /* Device busy */
+ SCMI_ERR_COMMS = -7, /* Communication Error */
+ SCMI_ERR_GENERIC = -8, /* Generic Error */
+ SCMI_ERR_HARDWARE = -9, /* Hardware Error */
+ SCMI_ERR_PROTOCOL = -10,/* Protocol Error */
+ SCMI_ERR_MAX
+};
+
+/* List of all SCMI devices active in system */
+static LIST_HEAD(scmi_list);
+/* Protection for the entire list */
+static DEFINE_MUTEX(scmi_list_mutex);
+
+/**
+ * struct scmi_xfers_info - Structure to manage transfer information
+ *
+ * @sem_xfer_count: Counting Semaphore for managing max simultaneous
+ * Messages.
+ * @xfer_block: Preallocated Message array
+ * @xfer_alloc_table: Bitmap table for allocated messages.
+ * Index of this bitmap table is also used for message
+ * sequence identifier.
+ * @xfer_lock: Protection for message allocation
+ */
+struct scmi_xfers_info {
+ struct semaphore sem_xfer_count;
+ struct scmi_xfer *xfer_block;
+ unsigned long *xfer_alloc_table;
+ /* protect transfer allocation */
+ spinlock_t xfer_lock;
+};
+
+/**
+ * struct scmi_desc - Description of SoC integration
+ *
+ * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
+ * @max_msg: Maximum number of messages that can be pending
+ * simultaneously in the system
+ * @max_msg_size: Maximum size of data per message that can be handled.
+ */
+struct scmi_desc {
+ int max_rx_timeout_ms;
+ int max_msg;
+ int max_msg_size;
+};
+
+/**
+ * struct scmi_info - Structure representing a SCMI instance
+ *
+ * @dev: Device pointer
+ * @desc: SoC description for this instance
+ * @handle: Instance of SCMI handle to send to clients
+ * @cl: Mailbox Client
+ * @tx_chan: Transmit mailbox channel
+ * @tx_payload: Transmit mailbox channel payload area
+ * @minfo: Message info
+ * @node: list head
+ * @users: Number of users of this instance
+ */
+struct scmi_info {
+ struct device *dev;
+ const struct scmi_desc *desc;
+ struct scmi_handle handle;
+ struct mbox_client cl;
+ struct mbox_chan *tx_chan;
+ void __iomem *tx_payload;
+ struct scmi_xfers_info minfo;
+ struct list_head node;
+ int users;
+};
+
+#define client_to_scmi_info(c) container_of(c, struct scmi_info, cl)
+#define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle)
+
+/*
+ * SCMI specification requires all parameters, message headers, return
+ * arguments or any protocol data to be expressed in little endian
+ * format only.
+ */
+struct scmi_shared_mem {
+ __le32 reserved;
+ __le32 channel_status;
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1)
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0)
+ __le32 reserved1[2];
+ __le32 flags;
+#define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0)
+ __le32 length;
+ __le32 msg_header;
+ u8 msg_payload[0];
+};
+
+static const int scmi_linux_errmap[] = {
+ /* better than switch case as long as return value is continuous */
+ 0, /* SCMI_SUCCESS */
+ -EOPNOTSUPP, /* SCMI_ERR_SUPPORT */
+ -EINVAL, /* SCMI_ERR_PARAM */
+ -EACCES, /* SCMI_ERR_ACCESS */
+ -ENOENT, /* SCMI_ERR_ENTRY */
+ -ERANGE, /* SCMI_ERR_RANGE */
+ -EBUSY, /* SCMI_ERR_BUSY */
+ -ECOMM, /* SCMI_ERR_COMMS */
+ -EIO, /* SCMI_ERR_GENERIC */
+ -EREMOTEIO, /* SCMI_ERR_HARDWARE */
+ -EPROTO, /* SCMI_ERR_PROTOCOL */
+};
+
+static inline int scmi_to_linux_errno(int errno)
+{
+ if (errno < SCMI_SUCCESS && errno > SCMI_ERR_MAX)
+ return scmi_linux_errmap[-errno];
+ return -EIO;
+}
+
+/**
+ * scmi_dump_header_dbg() - Helper to dump a message header.
+ *
+ * @dev: Device pointer corresponding to the SCMI entity
+ * @hdr: pointer to header.
+ */
+static inline void scmi_dump_header_dbg(struct device *dev,
+ struct scmi_msg_hdr *hdr)
+{
+ dev_dbg(dev, "Command ID: %x Sequence ID: %x Protocol: %x\n",
+ hdr->id, hdr->seq, hdr->protocol_id);
+}
+
+static void scmi_fetch_response(struct scmi_xfer *xfer,
+ struct scmi_shared_mem __iomem *mem)
+{
+ xfer->hdr.status = ioread32(mem->msg_payload);
+ /* Skip the length of header and statues in payload area i.e 8 bytes*/
+ xfer->rx.len = min_t(size_t, xfer->rx.len, ioread32(&mem->length) - 8);
+
+ /* Take a copy to the rx buffer.. */
+ memcpy_fromio(xfer->rx.buf, mem->msg_payload + 4, xfer->rx.len);
+}
+
+/**
+ * scmi_rx_callback() - mailbox client callback for receive messages
+ *
+ * @cl: client pointer
+ * @m: mailbox message
+ *
+ * Processes one received message to appropriate transfer information and
+ * signals completion of the transfer.
+ *
+ * NOTE: This function will be invoked in IRQ context, hence should be
+ * as optimal as possible.
+ */
+static void scmi_rx_callback(struct mbox_client *cl, void *m)
+{
+ u16 xfer_id;
+ struct scmi_xfer *xfer;
+ struct scmi_info *info = client_to_scmi_info(cl);
+ struct scmi_xfers_info *minfo = &info->minfo;
+ struct device *dev = info->dev;
+ struct scmi_shared_mem __iomem *mem = info->tx_payload;
+
+ xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header));
+
+ /*
+ * Are we even expecting this?
+ */
+ if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
+ dev_err(dev, "message for %d is not expected!\n", xfer_id);
+ return;
+ }
+
+ xfer = &minfo->xfer_block[xfer_id];
+
+ scmi_dump_header_dbg(dev, &xfer->hdr);
+ /* Is the message of valid length? */
+ if (xfer->rx.len > info->desc->max_msg_size) {
+ dev_err(dev, "unable to handle %zu xfer(max %d)\n",
+ xfer->rx.len, info->desc->max_msg_size);
+ return;
+ }
+
+ scmi_fetch_response(xfer, mem);
+ complete(&xfer->done);
+}
+
+/**
+ * pack_scmi_header() - packs and returns 32-bit header
+ *
+ * @hdr: pointer to header containing all the information on message id,
+ * protocol id and sequence id.
+ */
+static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
+{
+ return ((hdr->id & MSG_ID_MASK) << MSG_ID_SHIFT) |
+ ((hdr->seq & MSG_TOKEN_ID_MASK) << MSG_TOKEN_ID_SHIFT) |
+ ((hdr->protocol_id & MSG_PROTOCOL_ID_MASK) << MSG_PROTOCOL_ID_SHIFT);
+}
+
+/**
+ * scmi_tx_prepare() - mailbox client callback to prepare for the transfer
+ *
+ * @cl: client pointer
+ * @m: mailbox message
+ *
+ * This function prepares the shared memory which contains the header and the
+ * payload.
+ */
+static void scmi_tx_prepare(struct mbox_client *cl, void *m)
+{
+ struct scmi_xfer *t = m;
+ struct scmi_info *info = client_to_scmi_info(cl);
+ struct scmi_shared_mem __iomem *mem = info->tx_payload;
+
+ /* Mark channel busy + clear error */
+ iowrite32(0x0, &mem->channel_status);
+ iowrite32(t->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED,
+ &mem->flags);
+ iowrite32(sizeof(mem->msg_header) + t->tx.len, &mem->length);
+ iowrite32(pack_scmi_header(&t->hdr), &mem->msg_header);
+ if (t->tx.buf)
+ memcpy_toio(mem->msg_payload, t->tx.buf, t->tx.len);
+}
+
+/**
+ * scmi_one_xfer_get() - Allocate one message
+ *
+ * @handle: SCMI entity handle
+ *
+ * Helper function which is used by various command functions that are
+ * exposed to clients of this driver for allocating a message traffic event.
+ *
+ * This function can sleep depending on pending requests already in the system
+ * for the SCMI entity. Further, this also holds a spinlock to maintain
+ * integrity of internal data structures.
+ *
+ * Return: 0 if all went fine, else corresponding error.
+ */
+static struct scmi_xfer *scmi_one_xfer_get(const struct scmi_handle *handle)
+{
+ u16 xfer_id;
+ int ret, timeout;
+ struct scmi_xfer *xfer;
+ unsigned long flags, bit_pos;
+ struct scmi_info *info = handle_to_scmi_info(handle);
+ struct scmi_xfers_info *minfo = &info->minfo;
+
+ /*
+ * Ensure we have only controlled number of pending messages.
+ * Ideally, we might just have to wait a single message, be
+ * conservative and wait 5 times that..
+ */
+ timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms) * 5;
+ ret = down_timeout(&minfo->sem_xfer_count, timeout);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ /* Keep the locked section as small as possible */
+ spin_lock_irqsave(&minfo->xfer_lock, flags);
+ bit_pos = find_first_zero_bit(minfo->xfer_alloc_table,
+ info->desc->max_msg);
+ if (bit_pos == info->desc->max_msg) {
+ spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+ return ERR_PTR(-ENOMEM);
+ }
+ set_bit(bit_pos, minfo->xfer_alloc_table);
+ spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
+ xfer_id = bit_pos;
+
+ xfer = &minfo->xfer_block[xfer_id];
+ xfer->hdr.seq = xfer_id;
+ reinit_completion(&xfer->done);
+
+ return xfer;
+}
+
+/**
+ * scmi_one_xfer_put() - Release a message
+ *
+ * @minfo: transfer info pointer
+ * @xfer: message that was reserved by scmi_one_xfer_get
+ *
+ * This holds a spinlock to maintain integrity of internal data structures.
+ */
+void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+{
+ unsigned long flags;
+ struct scmi_info *info = handle_to_scmi_info(handle);
+ struct scmi_xfers_info *minfo = &info->minfo;
+
+ /*
+ * Keep the locked section as small as possible
+ * NOTE: we might escape with smp_mb and no lock here..
+ * but just be conservative and symmetric.
+ */
+ spin_lock_irqsave(&minfo->xfer_lock, flags);
+ clear_bit(xfer->hdr.seq, minfo->xfer_alloc_table);
+ spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
+ /* Increment the count for the next user to get through */
+ up(&minfo->sem_xfer_count);
+}
+
+/**
+ * scmi_do_xfer() - Do one transfer
+ *
+ * @info: Pointer to SCMI entity information
+ * @xfer: Transfer to initiate and wait for response
+ *
+ * Return: -ETIMEDOUT in case of no response, if transmit error,
+ * return corresponding error, else if all goes well,
+ * return 0.
+ */
+int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+{
+ int ret;
+ int timeout;
+ struct scmi_info *info = handle_to_scmi_info(handle);
+ struct device *dev = info->dev;
+
+ ret = mbox_send_message(info->tx_chan, xfer);
+ if (ret < 0) {
+ dev_dbg(dev, "mbox send fail %d\n", ret);
+ return ret;
+ }
+
+ /* mbox_send_message returns non-negative value on success, so reset */
+ ret = 0;
+
+ /* And we wait for the response. */
+ timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
+ if (!wait_for_completion_timeout(&xfer->done, timeout)) {
+ dev_err(dev, "mbox timed out in resp(caller: %pF)\n",
+ (void *)_RET_IP_);
+ ret = -ETIMEDOUT;
+ } else if (xfer->hdr.status) {
+ ret = scmi_to_linux_errno(xfer->hdr.status);
+ }
+ /*
+ * NOTE: we might prefer not to need the mailbox ticker to manage the
+ * transfer queueing since the protocol layer queues things by itself.
+ * Unfortunately, we have to kick the mailbox framework after we have
+ * received our message.
+ */
+ mbox_client_txdone(info->tx_chan, ret);
+
+ return ret;
+}
+
+/**
+ * scmi_one_xfer_init() - Allocate and initialise one message
+ *
+ * @handle: SCMI entity handle
+ * @msg_id: Message identifier
+ * @msg_prot_id: Protocol identifier for the message
+ * @tx_size: transmit message size
+ * @rx_size: receive message size
+ * @p: pointer to the allocated and initialised message
+ *
+ * This function allocates the message using @scmi_one_xfer_get and
+ * initialise the header.
+ *
+ * Return: 0 if all went fine with @p pointing to message, else
+ * corresponding error.
+ */
+int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
+ size_t tx_size, size_t rx_size, struct scmi_xfer **p)
+{
+ int ret;
+ struct scmi_xfer *xfer;
+ struct scmi_info *info = handle_to_scmi_info(handle);
+ struct device *dev = info->dev;
+
+ /* Ensure we have sane transfer sizes */
+ if (rx_size > info->desc->max_msg_size ||
+ tx_size > info->desc->max_msg_size)
+ return -ERANGE;
+
+ xfer = scmi_one_xfer_get(handle);
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ dev_err(dev, "failed to get free message slot(%d)\n", ret);
+ return ret;
+ }
+
+ xfer->tx.len = tx_size;
+ xfer->rx.len = rx_size ? : info->desc->max_msg_size;
+ xfer->hdr.id = msg_id;
+ xfer->hdr.protocol_id = prot_id;
+ xfer->hdr.poll_completion = false;
+
+ *p = xfer;
+ return 0;
+}
+
+/**
+ * scmi_handle_get() - Get the SCMI handle for a device
+ *
+ * @dev: pointer to device for which we want SCMI handle
+ *
+ * NOTE: The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of SCMI protocol library.
+ * scmi_handle_put must be balanced with successful scmi_handle_get
+ *
+ * Return: pointer to handle if successful, NULL on error
+ */
+struct scmi_handle *scmi_handle_get(struct device *dev)
+{
+ struct list_head *p;
+ struct scmi_info *info;
+ struct scmi_handle *handle = NULL;
+
+ mutex_lock(&scmi_list_mutex);
+ list_for_each(p, &scmi_list) {
+ info = list_entry(p, struct scmi_info, node);
+ if (dev->parent == info->dev) {
+ handle = &info->handle;
+ info->users++;
+ break;
+ }
+ }
+ mutex_unlock(&scmi_list_mutex);
+
+ return handle;
+}
+
+/**
+ * scmi_handle_put() - Release the handle acquired by scmi_handle_get
+ *
+ * @handle: handle acquired by scmi_handle_get
+ *
+ * NOTE: The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of SCMI protocol library.
+ * scmi_handle_put must be balanced with successful scmi_handle_get
+ *
+ * Return: 0 is successfully released
+ * if null was passed, it returns -EINVAL;
+ */
+int scmi_handle_put(const struct scmi_handle *handle)
+{
+ struct scmi_info *info;
+
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_scmi_info(handle);
+ mutex_lock(&scmi_list_mutex);
+ if (!WARN_ON(!info->users))
+ info->users--;
+ mutex_unlock(&scmi_list_mutex);
+
+ return 0;
+}
+
+static const struct scmi_desc scmi_generic_desc = {
+ .max_rx_timeout_ms = 30, /* we may increase this if required */
+ .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */
+ .max_msg_size = 128,
+};
+
+/* Each compatible listed below must have descriptor associated with it */
+static const struct of_device_id scmi_of_match[] = {
+ { .compatible = "arm,scmi", .data = &scmi_generic_desc },
+ { /* Sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, scmi_of_match);
+
+static int scmi_xfer_info_init(struct scmi_info *sinfo)
+{
+ int i;
+ struct scmi_xfer *xfer;
+ struct device *dev = sinfo->dev;
+ const struct scmi_desc *desc = sinfo->desc;
+ struct scmi_xfers_info *info = &sinfo->minfo;
+
+ /* Pre-allocated messages, no more than what hdr.seq can support */
+ if (WARN_ON(desc->max_msg >= (MSG_TOKEN_ID_MASK + 1))) {
+ dev_err(dev, "Maximum message of %d exceeds supported %d\n",
+ desc->max_msg, MSG_TOKEN_ID_MASK + 1);
+ return -EINVAL;
+ }
+
+ info->xfer_block = devm_kcalloc(dev, desc->max_msg,
+ sizeof(*info->xfer_block), GFP_KERNEL);
+ if (!info->xfer_block)
+ return -ENOMEM;
+
+ info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(desc->max_msg),
+ sizeof(long), GFP_KERNEL);
+ if (!info->xfer_alloc_table)
+ return -ENOMEM;
+
+ bitmap_zero(info->xfer_alloc_table, desc->max_msg);
+
+ /* Pre-initialize the buffer pointer to pre-allocated buffers */
+ for (i = 0, xfer = info->xfer_block; i < desc->max_msg; i++, xfer++) {
+ xfer->rx.buf = devm_kcalloc(dev, sizeof(u8), desc->max_msg_size,
+ GFP_KERNEL);
+ if (!xfer->rx.buf)
+ return -ENOMEM;
+
+ xfer->tx.buf = xfer->rx.buf;
+ init_completion(&xfer->done);
+ }
+
+ spin_lock_init(&info->xfer_lock);
+
+ sema_init(&info->sem_xfer_count, desc->max_msg);
+
+ return 0;
+}
+
+static int scmi_mailbox_check(struct device_node *np)
+{
+ struct of_phandle_args arg;
+
+ return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
+}
+
+static int scmi_mbox_free_channel(struct scmi_info *info)
+{
+ if (!IS_ERR_OR_NULL(info->tx_chan)) {
+ mbox_free_channel(info->tx_chan);
+ info->tx_chan = NULL;
+ }
+
+ return 0;
+}
+
+static int scmi_remove(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct scmi_info *info = platform_get_drvdata(pdev);
+
+ mutex_lock(&scmi_list_mutex);
+ if (info->users)
+ ret = -EBUSY;
+ else
+ list_del(&info->node);
+ mutex_unlock(&scmi_list_mutex);
+
+ if (!ret)
+ /* Safe to free channels since no more users */
+ return scmi_mbox_free_channel(info);
+
+ return ret;
+}
+
+static inline int scmi_mbox_chan_setup(struct scmi_info *info)
+{
+ int ret;
+ struct resource res;
+ resource_size_t size;
+ struct device *dev = info->dev;
+ struct device_node *shmem, *np = dev->of_node;
+ struct mbox_client *cl;
+
+ cl = &info->cl;
+ cl->dev = dev;
+ cl->rx_callback = scmi_rx_callback;
+ cl->tx_prepare = scmi_tx_prepare;
+ cl->tx_block = false;
+ cl->knows_txdone = true;
+
+ shmem = of_parse_phandle(np, "shmem", 0);
+ ret = of_address_to_resource(shmem, 0, &res);
+ of_node_put(shmem);
+ if (ret) {
+ dev_err(dev, "failed to get SCMI Tx payload mem resource\n");
+ return ret;
+ }
+
+ size = resource_size(&res);
+ info->tx_payload = devm_ioremap(dev, res.start, size);
+ if (!info->tx_payload) {
+ dev_err(dev, "failed to ioremap SCMI Tx payload\n");
+ return -EADDRNOTAVAIL;
+ }
+
+ /* Transmit channel is first entry i.e. index 0 */
+ info->tx_chan = mbox_request_channel(cl, 0);
+ if (IS_ERR(info->tx_chan)) {
+ ret = PTR_ERR(info->tx_chan);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to request SCMI Tx mailbox\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int scmi_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct scmi_handle *handle;
+ const struct scmi_desc *desc;
+ struct scmi_info *info;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+
+ /* Only mailbox method supported, check for the presence of one */
+ if (scmi_mailbox_check(np)) {
+ dev_err(dev, "no mailbox found in %pOF\n", np);
+ return -EINVAL;
+ }
+
+ desc = of_match_device(scmi_of_match, dev)->data;
+
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = dev;
+ info->desc = desc;
+ INIT_LIST_HEAD(&info->node);
+
+ ret = scmi_xfer_info_init(info);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, info);
+
+ handle = &info->handle;
+ handle->dev = info->dev;
+
+ ret = scmi_mbox_chan_setup(info);
+ if (ret)
+ return ret;
+
+ mutex_lock(&scmi_list_mutex);
+ list_add_tail(&info->node, &scmi_list);
+ mutex_unlock(&scmi_list_mutex);
+
+ return 0;
+}
+
+static struct platform_driver scmi_driver = {
+ .driver = {
+ .name = "arm-scmi",
+ .of_match_table = scmi_of_match,
+ },
+ .probe = scmi_probe,
+ .remove = scmi_remove,
+};
+
+module_platform_driver(scmi_driver);
+
+MODULE_ALIAS("platform: arm-scmi");
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI protocol driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
new file mode 100644
index 000000000000..854ed2479993
--- /dev/null
+++ b/include/linux/scmi_protocol.h
@@ -0,0 +1,27 @@
+/*
+ * SCMI Message Protocol driver header
+ *
+ * Copyright (C) 2017 ARM Ltd.
+ *
+ * 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/types.h>
+
+/**
+ * struct scmi_handle - Handle returned to ARM SCMI clients for usage.
+ *
+ * @dev: pointer to the SCMI device
+ */
+struct scmi_handle {
+ struct device *dev;
+};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 02/20] dt-bindings: arm: add support for ARM System Control and Management Interface(SCMI) protocol
From: Sudeep Holla @ 2018-01-02 14:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514904162-11201-1-git-send-email-sudeep.holla@arm.com>
This patch adds devicetree binding for System Control and Management
Interface (SCMI) Message Protocol used between the Application Cores(AP)
and the System Control Processor(SCP). The MHU peripheral provides a
mechanism for inter-processor communication between SCP's M3 processor
and AP.
SCP offers control and management of the core/cluster power states,
various power domain DVFS including the core/cluster, certain system
clocks configuration, thermal sensors and many others.
SCMI protocol is developed as better replacement to the existing SCPI
which is not flexible and easily extensible.
Cc: Mark Rutland <mark.rutland@arm.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
Documentation/devicetree/bindings/arm/arm,scmi.txt | 179 +++++++++++++++++++++
MAINTAINERS | 4 +-
2 files changed, 181 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/arm,scmi.txt
diff --git a/Documentation/devicetree/bindings/arm/arm,scmi.txt b/Documentation/devicetree/bindings/arm/arm,scmi.txt
new file mode 100644
index 000000000000..5f3719ab7075
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,scmi.txt
@@ -0,0 +1,179 @@
+System Control and Management Interface (SCMI) Message Protocol
+----------------------------------------------------------
+
+The SCMI is intended to allow agents such as OSPM to manage various functions
+that are provided by the hardware platform it is running on, including power
+and performance functions.
+
+This binding is intended to define the interface the firmware implementing
+the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control
+and Management Interface Platform Design Document")[0] provide for OSPM in
+the device tree.
+
+Required properties:
+
+The scmi node with the following properties shall be under the /firmware/ node.
+
+- compatible : shall be "arm,scmi"
+- mboxes: List of phandle and mailbox channel specifiers. It should contain
+ exactly one or two mailboxes, one for transmitting messages("tx")
+ and another optional for receiving the notifications("rx") if
+ supported.
+- shmem : List of phandle pointing to the shared memory(SHM) area as per
+ generic mailbox client binding.
+- #address-cells : should be '1' if the device has sub-nodes, maps to
+ protocol identifier for a given sub-node.
+- #size-cells : should be '0' as 'reg' property doesn't have any size
+ associated with it.
+
+Optional properties:
+
+- mbox-names: shall be "tx" or "rx" depending on mboxes entries.
+
+See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
+about the generic mailbox controller and client driver bindings.
+
+The mailbox is the only permitted method of calling the SCMI firmware.
+Mailbox doorbell is used as a mechanism to alert the presence of a
+messages and/or notification.
+
+Each protocol supported shall have a sub-node with corresponding compatible
+as described in the following sections. If the platform supports dedicated
+communication channel for a particular protocol, the 3 properties namely:
+mboxes, mbox-names and shmem shall be present in the sub-node corresponding
+to that protocol.
+
+Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol
+------------------------------------------------------------
+
+This binding uses the common clock binding[1].
+
+Required properties:
+- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands.
+
+Power domain bindings for the power domains based on SCMI Message Protocol
+------------------------------------------------------------
+
+This binding for the SCMI power domain providers uses the generic power
+domain binding[2].
+
+Required properties:
+ - #power-domain-cells : Should be 1. Contains the device or the power
+ domain ID value used by SCMI commands.
+
+Sensor bindings for the sensors based on SCMI Message Protocol
+--------------------------------------------------------------
+SCMI provides an API to access the various sensors on the SoC.
+
+Required properties:
+- #thermal-sensor-cells: should be set to 1. This property follows the
+ thermal device tree bindings[3].
+
+ Valid cell values are raw identifiers (Sensor ID)
+ as used by the firmware. Refer to platform details
+ for your implementation for the IDs to use.
+
+SRAM and Shared Memory for SCMI
+-------------------------------
+
+A small area of SRAM is reserved for SCMI communication between application
+processors and SCP.
+
+The properties should follow the generic mmio-sram description found in [4]
+
+Each sub-node represents the reserved area for SCMI.
+
+Required sub-node properties:
+- reg : The base offset and size of the reserved area with the SRAM
+- compatible : should be "arm,scmi-shmem" for Non-secure SRAM based
+ shared memory
+
+[0] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/power/power_domain.txt
+[3] Documentation/devicetree/bindings/thermal/thermal.txt
+[4] Documentation/devicetree/bindings/sram/sram.txt
+
+Example:
+
+sram at 50000000 {
+ compatible = "mmio-sram";
+ reg = <0x0 0x50000000 0x0 0x10000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x0 0x50000000 0x10000>;
+
+ cpu_scp_lpri: scp-shmem at 0 {
+ compatible = "arm,scmi-shmem";
+ reg = <0x0 0x200>;
+ };
+
+ cpu_scp_hpri: scp-shmem at 200 {
+ compatible = "arm,scmi-shmem";
+ reg = <0x200 0x200>;
+ };
+};
+
+mailbox at 40000000 {
+ ....
+ #mbox-cells = <1>;
+ reg = <0x0 0x40000000 0x0 0x10000>;
+};
+
+firmware {
+
+ ...
+
+ scmi {
+ compatible = "arm,scmi";
+ mboxes = <&mailbox 0 &mailbox 1>;
+ mbox-names = "tx", "rx";
+ shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ scmi_devpd: protocol at 11 {
+ reg = <0x11>;
+ #power-domain-cells = <1>;
+ };
+
+ scmi_dvfs: protocol at 13 {
+ reg = <0x13>;
+ #clock-cells = <1>;
+ };
+
+ scmi_clk: protocol at 14 {
+ reg = <0x14>;
+ #clock-cells = <1>;
+ };
+
+ scmi_sensors0: protocol at 15 {
+ reg = <0x15>;
+ #thermal-sensor-cells = <1>;
+ };
+ };
+};
+
+cpu at 0 {
+ ...
+ reg = <0 0>;
+ clocks = <&scmi_dvfs 0>;
+};
+
+hdlcd at 7ff60000 {
+ ...
+ reg = <0 0x7ff60000 0 0x1000>;
+ clocks = <&scmi_clk 4>;
+ power-domains = <&scmi_devpd 1>;
+};
+
+thermal-zones {
+ soc_thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <1000>;
+ /* sensor ID */
+ thermal-sensors = <&scmi_sensors0 3>;
+ ...
+ };
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index b46c9cea5ae5..56885de4ba44 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13149,11 +13149,11 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
S: Supported
F: drivers/mfd/syscon.c
-SYSTEM CONTROL & POWER INTERFACE (SCPI) Message Protocol drivers
+SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE (SCPI/SCMI) Message Protocol drivers
M: Sudeep Holla <sudeep.holla@arm.com>
L: linux-arm-kernel at lists.infradead.org
S: Maintained
-F: Documentation/devicetree/bindings/arm/arm,scpi.txt
+F: Documentation/devicetree/bindings/arm/arm,sc[mp]i.txt
F: drivers/clk/clk-scpi.c
F: drivers/cpufreq/scpi-cpufreq.c
F: drivers/firmware/arm_scpi.c
--
2.7.4
^ permalink raw reply related
* [PATCH v5 01/20] dt-bindings: mailbox: add support for mailbox client shared memory
From: Sudeep Holla @ 2018-01-02 14:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514904162-11201-1-git-send-email-sudeep.holla@arm.com>
Many users of the mailbox controllers depend on the shared memory
between the two end points to exchange the main data while using simple
doorbell mechanism to alert the end points of the presence of a message.
This patch defines device tree bindings to represent such shared memory
in a generic way.
Cc: Mark Rutland <mark.rutland@arm.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
.../devicetree/bindings/mailbox/mailbox.txt | 28 ++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/Documentation/devicetree/bindings/mailbox/mailbox.txt b/Documentation/devicetree/bindings/mailbox/mailbox.txt
index be05b9746c69..af8ecee2ac68 100644
--- a/Documentation/devicetree/bindings/mailbox/mailbox.txt
+++ b/Documentation/devicetree/bindings/mailbox/mailbox.txt
@@ -23,6 +23,11 @@ assign appropriate mailbox channel to client drivers.
Optional property:
- mbox-names: List of identifier strings for each mailbox channel.
+- shmem : List of phandle pointing to the shared memory(SHM) area between the
+ users of these mailboxes for IPC, one for each mailbox. This shared
+ memory can be part of any memory reserved for the purpose of this
+ communication between the mailbox client and the remote.
+
Example:
pwr_cntrl: power {
@@ -30,3 +35,26 @@ assign appropriate mailbox channel to client drivers.
mbox-names = "pwr-ctrl", "rpc";
mboxes = <&mailbox 0 &mailbox 1>;
};
+
+Example with shared memory(shmem):
+
+ sram: sram at 50000000 {
+ compatible = "mmio-sram";
+ reg = <0x50000000 0x10000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x50000000 0x10000>;
+
+ cl_shmem: shmem at 0 {
+ compatible = "client-shmem";
+ reg = <0x0 0x200>;
+ };
+ };
+
+ client at 2e000000 {
+ ...
+ mboxes = <&mailbox 0>;
+ shmem = <&cl_shmem>;
+ ..
+ };
--
2.7.4
^ permalink raw reply related
* [PATCH v5 00/20] firmware: ARM System Control and Management Interface(SCMI) support
From: Sudeep Holla @ 2018-01-02 14:42 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
ARM System Control and Management Interface(SCMI) is more flexible and
easily extensible than any of the existing interfaces. Many vendors were
involved in the making of this formal specification and is now published[1].
There is a strong trend in the industry to provide micro-controllers in
systems to abstract various power, or other system management tasks.
These controllers usually have similar interfaces, both in terms of the
functions that are provided by them, and in terms of how requests are
communicated to them.
This specification is to standardise and avoid (any further)
fragmentation in the design of such interface by various vendors.
This patch set is intended to get feedback on the design and structure
of the code. This is not complete and not fully tested due to
non-availability of firmware with full feature set at this time.
It currently doesn't support notification, asynchronous/delayed response,
perf/power statistics region and sensor register region to name a few.
I have borrowed some of the ideas of message allocation/management from
TI SCI.
Changes:
v4[6]->v5:
- Rebased to v4.15-rc6
- Updated all the gathered Ack/Reviewed-by tags(which includes
all the drivers using SCMI protocol)
v3[5]->v4[6]:
- Added SCMI protocol bus to enumerate supported protocols as
suggested by Arnd
- Dropped the abstraction to mailbox as it may be optional
v2[4]->v3:
- Addressed various comments recieved so far(clock, hwmon and
cpufreq drivers along with scmi drivers)
- Hwmon driver now uses core layer to create and manage sysfs
attributes
- Added a shim layer to abstract the mailbox interface to support
any custom adaptation required by the controller driver
- Simple ARM MHU shim layer using newly added abstraction
v1[3]->v2[4]:
- Additional support for polling based DVFS and per protocol
channels
- Dependent drivers(clock, hwmon, cpufreq and power domains)
- Various other review comments and issued found during testing
addressed
- Explicit binding for method dropped as even SMC based method
are adviertised as mailbox
RFC[2]->v1[3]:
- Add generic mailbox binding for shared memory(Rob H)
- Dropped compatibles per protocol(Suggested by Matt S)
- Dropped lot of unnecessary pointer casting(Arnd B)
- Dropped packing of structures(Arnd B)
- Few other changes/additions based initial testing with firmware
providing SCMI interface to OSPM
--
Regards,
Sudeep
[1] http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/index.html
[2] https://marc.info/?l=linux-kernel&m=149685193627620&w=2
[3] https://marc.info/?l=linux-arm-kernel&m=149849482623492&w=2
[4] https://marc.info/?l=devicetree&m=150185763105926&w=2
[5] https://marc.info/?l=devicetree&m=150660452015351&w=2
[6] https://marc.info/?l=devicetree&m=150972061408961&w=2
Sudeep Holla (20):
dt-bindings: mailbox: add support for mailbox client shared memory
dt-bindings: arm: add support for ARM System Control and Management
Interface(SCMI) protocol
firmware: arm_scmi: add basic driver infrastructure for SCMI
firmware: arm_scmi: add common infrastructure and support for base
protocol
firmware: arm_scmi: add scmi protocol bus to enumerate protocol
devices
firmware: arm_scmi: add initial support for performance protocol
firmware: arm_scmi: add initial support for clock protocol
firmware: arm_scmi: add initial support for power protocol
firmware: arm_scmi: add initial support for sensor protocol
firmware: arm_scmi: probe and initialise all the supported protocols
firmware: arm_scmi: add support for polling based SCMI transfers
firmware: arm_scmi: add option for polling based performance domain
operations
firmware: arm_scmi: refactor in preparation to support per-protocol
channels
firmware: arm_scmi: add per-protocol channels support using idr
objects
firmware: arm_scmi: add device power domain support using genpd
clk: add support for clocks provided by SCMI
hwmon: (core) Add hwmon_max to hwmon_sensor_types enumeration
hwmon: add support for sensors exported via ARM SCMI
cpufreq: add support for CPU DVFS based on SCMI message protocol
cpufreq: scmi: add support for fast frequency switching
Documentation/devicetree/bindings/arm/arm,scmi.txt | 179 +++++
.../devicetree/bindings/mailbox/mailbox.txt | 28 +
MAINTAINERS | 11 +-
drivers/clk/Kconfig | 10 +
drivers/clk/Makefile | 1 +
drivers/clk/clk-scmi.c | 213 +++++
drivers/cpufreq/Kconfig.arm | 11 +
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/scmi-cpufreq.c | 285 +++++++
drivers/firmware/Kconfig | 34 +
drivers/firmware/Makefile | 1 +
drivers/firmware/arm_scmi/Makefile | 5 +
drivers/firmware/arm_scmi/base.c | 293 +++++++
drivers/firmware/arm_scmi/bus.c | 232 ++++++
drivers/firmware/arm_scmi/clock.c | 353 ++++++++
drivers/firmware/arm_scmi/common.h | 116 +++
drivers/firmware/arm_scmi/driver.c | 895 +++++++++++++++++++++
drivers/firmware/arm_scmi/perf.c | 530 ++++++++++++
drivers/firmware/arm_scmi/power.c | 255 ++++++
drivers/firmware/arm_scmi/scmi_pm_domain.c | 140 ++++
drivers/firmware/arm_scmi/sensors.c | 302 +++++++
drivers/hwmon/Kconfig | 12 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/scmi-hwmon.c | 233 ++++++
include/linux/hwmon.h | 1 +
include/linux/scmi_protocol.h | 272 +++++++
26 files changed, 4409 insertions(+), 5 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/arm,scmi.txt
create mode 100644 drivers/clk/clk-scmi.c
create mode 100644 drivers/cpufreq/scmi-cpufreq.c
create mode 100644 drivers/firmware/arm_scmi/Makefile
create mode 100644 drivers/firmware/arm_scmi/base.c
create mode 100644 drivers/firmware/arm_scmi/bus.c
create mode 100644 drivers/firmware/arm_scmi/clock.c
create mode 100644 drivers/firmware/arm_scmi/common.h
create mode 100644 drivers/firmware/arm_scmi/driver.c
create mode 100644 drivers/firmware/arm_scmi/perf.c
create mode 100644 drivers/firmware/arm_scmi/power.c
create mode 100644 drivers/firmware/arm_scmi/scmi_pm_domain.c
create mode 100644 drivers/firmware/arm_scmi/sensors.c
create mode 100644 drivers/hwmon/scmi-hwmon.c
create mode 100644 include/linux/scmi_protocol.h
--
2.7.4
^ permalink raw reply
* [PATCH 2/2] cpufreq: imx6q: add 696MHz operating point for i.mx6ul
From: Fabio Estevam @ 2018-01-02 14:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514912859-17691-2-git-send-email-Anson.Huang@nxp.com>
Hi Anson,
On Tue, Jan 2, 2018 at 3:07 PM, Anson Huang <Anson.Huang@nxp.com> wrote:
> diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
> index d9b2c2d..cbda0cc 100644
> --- a/drivers/cpufreq/imx6q-cpufreq.c
> +++ b/drivers/cpufreq/imx6q-cpufreq.c
> @@ -120,6 +120,10 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
> clk_set_parent(secondary_sel_clk, pll2_pfd2_396m_clk);
> clk_set_parent(step_clk, secondary_sel_clk);
> clk_set_parent(pll1_sw_clk, step_clk);
> + if (freq_hz > clk_get_rate(pll2_bus_clk)) {
> + clk_set_rate(pll1_sys_clk, new_freq * 1000);
> + clk_set_parent(pll1_sw_clk, pll1_sys_clk);
> + }
This change should be part of a different patch.
Thanks
^ permalink raw reply
* [net-next: PATCH v2 5/5] net: mvpp2: enable ACPI support in the driver
From: Andrew Lunn @ 2018-01-02 14:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPv3WKfB6_5hPw2M_GOMHVc_soPyzgMqQJ=tG5qOfSe_397z9A@mail.gmail.com>
> Indeed in of_mdio_bus_register_phy, there is of_irq_get. This is more
> a discussion for a MDIO bus / ACPI patchset, but we either find a way
> to use IRQs with ACPI obtained from child nodes or for this world the
> functionality will be limited (at least for the beginning).
Hi Marcin
What i want to avoid is adding something which partially works, and
then have to throw it all away and start again in order to add full
support.
If ACPI really limits interrupts to devices, maybe we need a totally
different representation of MDIO and PHYs in ACPI to what it used in
device tree? The same may be true for the Ethernet ports of the mvpp2?
They might have to be represented as real devices, not children of a
device? Maybe trying to map DT to ACPI on a one-to-one basis is the
wrong approach?
Andrew
^ permalink raw reply
* [PATCH v3 0/2] Avoid calling cpu_pm functions for retention idle states
From: Catalin Marinas @ 2018-01-02 14:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1510765910-23739-1-git-send-email-pprakash@codeaurora.org>
On Wed, Nov 15, 2017 at 10:11:48AM -0700, Prashanth Prakash wrote:
> CPU_PM_CPU_IDLE_ENTER() treats all idle states whose idx != 0 as a
> state that loses some context, but we can have deeper idle states that
> doesn't lose any software context. If a CPU is entering such a low power
> idle state where it retains the context, then there is no need to call
> cpu_pm_enter()/cpu_pm_exit().
>
> Add a new macro(CPU_PM_CPU_IDLE_ENTER_RETENTION) to be used by cpuidle
> drivers when they are entering retention state. By not calling cpu_pm_enter
> and cpu_pm_exit we reduce the latency involved in entering and exiting
> the retention states.
>
> On ARM64 based Qualcomm server platform we measured below overhead for
> for calling cpu_pm_enter and cpu_pm_exit for retention states.
>
> workload: stress --hdd #CPUs --hdd-bytes 32M -t 30
> Overhead of cpu_pm_enter - 1.2us(Average), 6.5us(Max)
> Overhead of cpu_pm_exit - 3.1us(Average), 11.1us(Max)
I queued the patches in the arm64 tree for 4.16. Thanks.
--
Catalin
^ permalink raw reply
* [Cluster-devel] [PATCH 00/12] drop unneeded newline
From: Julia Lawall @ 2018-01-02 14:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1019862289.2632779.1514901387442.JavaMail.zimbra@redhat.com>
On Tue, 2 Jan 2018, Bob Peterson wrote:
> ----- Original Message -----
> | ----- Original Message -----
> | | Drop newline at the end of a message string when the printing function adds
> | | a newline.
> |
> | Hi Julia,
> |
> | NACK.
> |
> | As much as it's a pain when searching the source code for output strings,
> | this patch set goes against the accepted Linux coding style document. See:
> |
> | https://www.kernel.org/doc/html/v4.10/process/coding-style.html#breaking-long-lines-and-strings
> |
> | Regards,
> |
> | Bob Peterson
> |
> |
> Hm. I guess I stand corrected. The document reads:
>
> "However, never break user-visible strings such as printk messages, because that breaks the ability to grep for them."
>
> Still, the GFS2 and DLM code has a plethora of broken-up printk messages,
> and I don't like the thought of re-combining them all.
Actually, the point of the patch was to remove the unnecessary \n at the
end of the string, because log_print will add another one. If you prefer
to keep the string broken up, I can resend the patch in that form, but
without the unnecessary \n.
julia
^ permalink raw reply
* [Cluster-devel] [PATCH 00/12] drop unneeded newline
From: Bob Peterson @ 2018-01-02 13:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1878806802.2632123.1514901158666.JavaMail.zimbra@redhat.com>
----- Original Message -----
| ----- Original Message -----
| | Drop newline at the end of a message string when the printing function adds
| | a newline.
|
| Hi Julia,
|
| NACK.
|
| As much as it's a pain when searching the source code for output strings,
| this patch set goes against the accepted Linux coding style document. See:
|
| https://www.kernel.org/doc/html/v4.10/process/coding-style.html#breaking-long-lines-and-strings
|
| Regards,
|
| Bob Peterson
|
|
Hm. I guess I stand corrected. The document reads:
"However, never break user-visible strings such as printk messages, because that breaks the ability to grep for them."
Still, the GFS2 and DLM code has a plethora of broken-up printk messages,
and I don't like the thought of re-combining them all.
Regards,
Bob Peterson
^ permalink raw reply
* [net-next: PATCH v2 5/5] net: mvpp2: enable ACPI support in the driver
From: Marcin Wojtas @ 2018-01-02 13:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180102133347.GB15036@lunn.ch>
Hi Andrew,
2018-01-02 14:33 GMT+01:00 Andrew Lunn <andrew@lunn.ch>:
>> Apart from the phylink's SFP support that may require in-band
>> management, it's an alternative to the normal PHY handling. Once MDIO
>> bus + PHYs are supported for ACPI, phylib support will be used instead
>> of the IRQs, so there should be no problem here.
>
> Hi Marcin
>
> However, phylib and phylink can use IRQs. The PHY can interrupt when
> there is a change of state. This can be seen in the DT binding
> documentation example:
>
> ethernet-phy at 0 {
> compatible = "ethernet-phy-id0141.0e90", "ethernet-phy-ieee802.3-c22";
> interrupt-parent = <&PIC>;
> interrupts = <35 IRQ_TYPE_EDGE_RISING>;
> reg = <0>;
>
> Whatever ACPI support you propose needs to include interrupts.
>
> May i suggest you take a look at
> arch/arm/boot/dts/vf610-zii-dev-rev-c.dts and ensure your ACPI work
> can support this. I know you tend to concentrate of Marvell parts.
> Although it is a Freescale SoC, the Ethernet parts are all Marvell.
>
> The SoC exports an MDIO bus. We then have an MDIO multiplexer, which
> exports 8 MDIO busses. Of these only 2 are used in this design. Each
> bus has an Ethernet switch. Each switch has an MDIO bus, which the
> embedded PHYs are on. The Ethernet switch is also an interrupt
> controller for the PHYs interrupts. So the PHYs have interrupt
> properties pointing back to the switch.
>
I thought you were pointing possible problems in mvpp2 with PHY/link
interrupts, sorry. Now I get it :)
Indeed in of_mdio_bus_register_phy, there is of_irq_get. This is more
a discussion for a MDIO bus / ACPI patchset, but we either find a way
to use IRQs with ACPI obtained from child nodes or for this world the
functionality will be limited (at least for the beginning).
Best regards,
Marcin
^ permalink raw reply
* [Cluster-devel] [PATCH 00/12] drop unneeded newline
From: Julia Lawall @ 2018-01-02 13:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1878806802.2632123.1514901158666.JavaMail.zimbra@redhat.com>
On Tue, 2 Jan 2018, Bob Peterson wrote:
> ----- Original Message -----
> | Drop newline at the end of a message string when the printing function adds
> | a newline.
>
> Hi Julia,
>
> NACK.
>
> As much as it's a pain when searching the source code for output strings,
> this patch set goes against the accepted Linux coding style document. See:
>
> https://www.kernel.org/doc/html/v4.10/process/coding-style.html#breaking-long-lines-and-strings
I don't think that's the case:
"However, never break user-visible strings such as printk messages,
because that breaks the ability to grep for them."
julia
>
> Regards,
>
> Bob Peterson
> --
> To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [Cluster-devel] [PATCH 00/12] drop unneeded newline
From: Bob Peterson @ 2018-01-02 13:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514386305-7402-1-git-send-email-Julia.Lawall@lip6.fr>
----- Original Message -----
| Drop newline at the end of a message string when the printing function adds
| a newline.
Hi Julia,
NACK.
As much as it's a pain when searching the source code for output strings,
this patch set goes against the accepted Linux coding style document. See:
https://www.kernel.org/doc/html/v4.10/process/coding-style.html#breaking-long-lines-and-strings
Regards,
Bob Peterson
^ permalink raw reply
* [PATCH V4 25/26] i7300_idle: remove unused file
From: Greg Kroah-Hartman @ 2018-01-02 13:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <121cd93d-562c-8ebd-21df-1dafbc525c80@codeaurora.org>
On Tue, Jan 02, 2018 at 08:36:46AM -0500, Sinan Kaya wrote:
> Hi Greg,
>
> On 12/19/2017 12:38 AM, Sinan Kaya wrote:
> > i7300_idle.h is not being called by any source file and contains calls to
> > pci_get_bus_and_slot() that we are trying to deprecate. Remove unused file.
> >
> > Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
>
> Do you think you can pick this up?
Sure, will do so, thanks.
greg k-h
^ permalink raw reply
* [PATCH V4 22/26] video: fbdev: intelfb: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2018-01-02 13:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513661883-28662-23-git-send-email-okaya@codeaurora.org>
On 12/19/2017 12:37 AM, Sinan Kaya wrote:
> pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> where a PCI device is present. This restricts the device drivers to be
> reused for other domain numbers.
>
> Getting ready to remove pci_get_bus_and_slot() function in favor of
> pci_get_domain_bus_and_slot().
>
> Find the domain number from pdev.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Any feedback here ? most of the remaining patches have the ACK except these.
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH V4 23/26] video: fbdev: nvidia: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2018-01-02 13:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513661883-28662-24-git-send-email-okaya@codeaurora.org>
On 12/19/2017 12:37 AM, Sinan Kaya wrote:
> pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> where a PCI device is present. This restricts the device drivers to be
> reused for other domain numbers.
>
> Getting ready to remove pci_get_bus_and_slot() function in favor of
> pci_get_domain_bus_and_slot().
>
> struct nvidia_par has a pointer to struct pci_dev. Use the pci_dev
> member to extract the domain information and pass it to
> pci_get_domain_bus_and_slot() function.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Any feedback here ? most of the remaining patches have the ACK except these.
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH V4 24/26] video: fbdev: riva: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2018-01-02 13:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513661883-28662-25-git-send-email-okaya@codeaurora.org>
On 12/19/2017 12:38 AM, Sinan Kaya wrote:
> pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> where a PCI device is present. This restricts the device drivers to be
> reused for other domain numbers.
>
> Getting ready to remove pci_get_bus_and_slot() function in favor of
> pci_get_domain_bus_and_slot().
>
> struct riva_par has a pointer to struct pci_dev. Use the pci_dev member
> to extract the domain information.
>
> Change the function signature for CalcStateExt and RivaGetConfig to pass
> in struct pci_dev in addition to RIVA_HW_INST so that code inside the
> riva_hw.c can also calculate domain number and pass it to
> pci_get_domain_bus_and_slot().
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Any feedback here, most of the remaining patches have the ACK except these?
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH V4 25/26] i7300_idle: remove unused file
From: Sinan Kaya @ 2018-01-02 13:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513661883-28662-26-git-send-email-okaya@codeaurora.org>
Hi Greg,
On 12/19/2017 12:38 AM, Sinan Kaya wrote:
> i7300_idle.h is not being called by any source file and contains calls to
> pci_get_bus_and_slot() that we are trying to deprecate. Remove unused file.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Do you think you can pick this up?
I'll start pinging all the remaining patches.
Sinan
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [net-next: PATCH v2 5/5] net: mvpp2: enable ACPI support in the driver
From: Andrew Lunn @ 2018-01-02 13:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPv3WKdr8MaPJi1_PnMfmmk3PeSrJBLUoE8gRCEzwbJsMKBaZg@mail.gmail.com>
> Apart from the phylink's SFP support that may require in-band
> management, it's an alternative to the normal PHY handling. Once MDIO
> bus + PHYs are supported for ACPI, phylib support will be used instead
> of the IRQs, so there should be no problem here.
Hi Marcin
However, phylib and phylink can use IRQs. The PHY can interrupt when
there is a change of state. This can be seen in the DT binding
documentation example:
ethernet-phy at 0 {
compatible = "ethernet-phy-id0141.0e90", "ethernet-phy-ieee802.3-c22";
interrupt-parent = <&PIC>;
interrupts = <35 IRQ_TYPE_EDGE_RISING>;
reg = <0>;
Whatever ACPI support you propose needs to include interrupts.
May i suggest you take a look at
arch/arm/boot/dts/vf610-zii-dev-rev-c.dts and ensure your ACPI work
can support this. I know you tend to concentrate of Marvell parts.
Although it is a Freescale SoC, the Ethernet parts are all Marvell.
The SoC exports an MDIO bus. We then have an MDIO multiplexer, which
exports 8 MDIO busses. Of these only 2 are used in this design. Each
bus has an Ethernet switch. Each switch has an MDIO bus, which the
embedded PHYs are on. The Ethernet switch is also an interrupt
controller for the PHYs interrupts. So the PHYs have interrupt
properties pointing back to the switch.
Andrew
^ permalink raw reply
* [PATCH 12/12] power: reset: account for const type of of_device_id.data
From: Julia Lawall @ 2018-01-02 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514899688-27844-1-git-send-email-Julia.Lawall@lip6.fr>
This driver creates a const structure that it stores in the data
field of an of_device_id array.
Add const to the declaration of the location that receives a value
from the data field to ensure that the compiler will continue to check
that the value is not modified and remove the const-dropping cast on
the access to the data field.
Done using Coccinelle.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/power/reset/at91-sama5d2_shdwc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff -u -p a/drivers/power/reset/at91-sama5d2_shdwc.c b/drivers/power/reset/at91-sama5d2_shdwc.c
--- a/drivers/power/reset/at91-sama5d2_shdwc.c
+++ b/drivers/power/reset/at91-sama5d2_shdwc.c
@@ -68,7 +68,7 @@ struct shdwc_config {
};
struct shdwc {
- struct shdwc_config *cfg;
+ const struct shdwc_config *cfg;
void __iomem *at91_shdwc_base;
};
@@ -260,7 +260,7 @@ static int __init at91_shdwc_probe(struc
}
match = of_match_node(at91_shdwc_of_match, pdev->dev.of_node);
- at91_shdwc->cfg = (struct shdwc_config *)(match->data);
+ at91_shdwc->cfg = match->data;
sclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(sclk))
^ permalink raw reply
* [PATCH 07/12] i2c: rk3x: account for const type of of_device_id.data
From: Julia Lawall @ 2018-01-02 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514899688-27844-1-git-send-email-Julia.Lawall@lip6.fr>
This driver creates a number of const structures that it stores in
the data field of an of_device_id array.
The data field of an of_device_id structure has type const void *, so
there is no need for a const-discarding cast when putting const values
into such a structure.
Furthermore, adding const to the declaration of the location that
receives a const value from such a field ensures that the compiler
will continue to check that the value is not modified. The
const-discarding cast on the extraction from the data field is thus
no longer needed.
Done using Coccinelle.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/i2c/busses/i2c-rk3x.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff -u -p a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -194,7 +194,7 @@ struct rk3x_i2c_soc_data {
struct rk3x_i2c {
struct i2c_adapter adap;
struct device *dev;
- struct rk3x_i2c_soc_data *soc_data;
+ const struct rk3x_i2c_soc_data *soc_data;
/* Hardware resources */
void __iomem *regs;
@@ -1164,27 +1164,27 @@ static const struct rk3x_i2c_soc_data rk
static const struct of_device_id rk3x_i2c_match[] = {
{
.compatible = "rockchip,rv1108-i2c",
- .data = (void *)&rv1108_soc_data
+ .data = &rv1108_soc_data
},
{
.compatible = "rockchip,rk3066-i2c",
- .data = (void *)&rk3066_soc_data
+ .data = &rk3066_soc_data
},
{
.compatible = "rockchip,rk3188-i2c",
- .data = (void *)&rk3188_soc_data
+ .data = &rk3188_soc_data
},
{
.compatible = "rockchip,rk3228-i2c",
- .data = (void *)&rk3228_soc_data
+ .data = &rk3228_soc_data
},
{
.compatible = "rockchip,rk3288-i2c",
- .data = (void *)&rk3288_soc_data
+ .data = &rk3288_soc_data
},
{
.compatible = "rockchip,rk3399-i2c",
- .data = (void *)&rk3399_soc_data
+ .data = &rk3399_soc_data
},
{},
};
@@ -1207,7 +1207,7 @@ static int rk3x_i2c_probe(struct platfor
return -ENOMEM;
match = of_match_node(rk3x_i2c_match, np);
- i2c->soc_data = (struct rk3x_i2c_soc_data *)match->data;
+ i2c->soc_data = match->data;
/* use common interface to get I2C timing properties */
i2c_parse_fw_timings(&pdev->dev, &i2c->t, true);
^ permalink raw reply
* [PATCH 05/12] pinctrl: armada-37xx: account for const type of of_device_id.data
From: Julia Lawall @ 2018-01-02 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514899688-27844-1-git-send-email-Julia.Lawall@lip6.fr>
The data field of an of_device_id structure has type const void *, so
there is no need for a const-discarding cast when putting const values
into such a structure.
Done using Coccinelle.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff -u -p a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -1006,11 +1006,11 @@ static int armada_37xx_pinctrl_register(
static const struct of_device_id armada_37xx_pinctrl_of_match[] = {
{
.compatible = "marvell,armada3710-sb-pinctrl",
- .data = (void *)&armada_37xx_pin_sb,
+ .data = &armada_37xx_pin_sb,
},
{
.compatible = "marvell,armada3710-nb-pinctrl",
- .data = (void *)&armada_37xx_pin_nb,
+ .data = &armada_37xx_pin_nb,
},
{ },
};
^ permalink raw reply
* [PATCH 03/12] spi: sirf: account for const type of of_device_id.data
From: Julia Lawall @ 2018-01-02 13:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514899688-27844-1-git-send-email-Julia.Lawall@lip6.fr>
This driver creates various const structures that it stores in the
data field of an of_device_id array.
Adding const to the declaration of the location that receives the
const value from the data field ensures that the compiler will
continue to check that the value is not modified. Furthermore, the
const-discarding cast on the extraction from the data field is no
longer needed.
Done using Coccinelle.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/spi/spi-sirf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff -u -p a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -1072,7 +1072,7 @@ static int spi_sirfsoc_probe(struct plat
struct sirfsoc_spi *sspi;
struct spi_master *master;
struct resource *mem_res;
- struct sirf_spi_comp_data *spi_comp_data;
+ const struct sirf_spi_comp_data *spi_comp_data;
int irq;
int ret;
const struct of_device_id *match;
@@ -1092,7 +1092,7 @@ static int spi_sirfsoc_probe(struct plat
platform_set_drvdata(pdev, master);
sspi = spi_master_get_devdata(master);
sspi->fifo_full_offset = ilog2(sspi->fifo_size);
- spi_comp_data = (struct sirf_spi_comp_data *)match->data;
+ spi_comp_data = match->data;
sspi->regs = spi_comp_data->regs;
sspi->type = spi_comp_data->type;
sspi->fifo_level_chk_mask = (sspi->fifo_size / 4) - 1;
^ permalink raw reply
* [PATCH 02/12] pinctrl: at91-pio4: account for const type of of_device_id.data
From: Julia Lawall @ 2018-01-02 13:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514899688-27844-1-git-send-email-Julia.Lawall@lip6.fr>
This driver creates a const structure that it stores in the data field
of an of_device_id array.
Adding const to the declaration of the location that receives the
const value from the data field ensures that the compiler will
continue to check that the value is not modified. Furthermore, the
const-discarding cast on the extraction from the data field is no
longer needed.
Done using Coccinelle.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/pinctrl/pinctrl-at91-pio4.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff -u -p a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -910,7 +910,7 @@ static int atmel_pinctrl_probe(struct pl
int i, ret;
struct resource *res;
struct atmel_pioctrl *atmel_pioctrl;
- struct atmel_pioctrl_data *atmel_pioctrl_data;
+ const struct atmel_pioctrl_data *atmel_pioctrl_data;
atmel_pioctrl = devm_kzalloc(dev, sizeof(*atmel_pioctrl), GFP_KERNEL);
if (!atmel_pioctrl)
@@ -924,7 +924,7 @@ static int atmel_pinctrl_probe(struct pl
dev_err(dev, "unknown compatible string\n");
return -ENODEV;
}
- atmel_pioctrl_data = (struct atmel_pioctrl_data *)match->data;
+ atmel_pioctrl_data = match->data;
atmel_pioctrl->nbanks = atmel_pioctrl_data->nbanks;
atmel_pioctrl->npins = atmel_pioctrl->nbanks * ATMEL_PIO_NPINS_PER_BANK;
^ 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