esoc: Snapshot esoc drivers

Snapshot esoc components, headers and UAPI headers from
msm-3.18@24d0c1f91eb2850
(Merge "msm: mdss: dp: handle fast attention events")

Change-Id: I55e7ea4359c1f5b855f082e66d5816316da2fd48
Signed-off-by: Abhimanyu Kapur <abhimany@codeaurora.org>
(cherry picked from commit 5d8ee90e7f7e576b877813535d08a4123bedc49e)
Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
diff --git a/drivers/esoc/esoc_client.c b/drivers/esoc/esoc_client.c
new file mode 100644
index 0000000..5b194e31
--- /dev/null
+++ b/drivers/esoc/esoc_client.c
@@ -0,0 +1,132 @@
+/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/esoc_client.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include "esoc.h"
+
+static DEFINE_SPINLOCK(notify_lock);
+static ATOMIC_NOTIFIER_HEAD(client_notify);
+
+static void devm_esoc_desc_release(struct device *dev, void *res)
+{
+	struct esoc_desc *esoc_desc = res;
+
+	kfree(esoc_desc->name);
+	kfree(esoc_desc->link);
+	put_esoc_clink(esoc_desc->priv);
+}
+
+static int devm_esoc_desc_match(struct device *dev, void *res, void *data)
+{
+	struct esoc_desc *esoc_desc = res;
+	return esoc_desc == data;
+}
+
+struct esoc_desc *devm_register_esoc_client(struct device *dev,
+							const char *name)
+{
+	int ret, index;
+	const char *client_desc;
+	char *esoc_prop;
+	const __be32 *parp;
+	struct device_node *esoc_node;
+	struct device_node *np = dev->of_node;
+	struct esoc_clink *esoc_clink;
+	struct esoc_desc *desc;
+	char *esoc_name, *esoc_link;
+
+	for (index = 0;; index++) {
+		esoc_prop = kasprintf(GFP_KERNEL, "esoc-%d", index);
+		parp = of_get_property(np, esoc_prop, NULL);
+		if (parp == NULL) {
+			dev_err(dev, "esoc device not present\n");
+			kfree(esoc_prop);
+			return NULL;
+		}
+		ret = of_property_read_string_index(np, "esoc-names", index,
+								&client_desc);
+		if (ret) {
+			dev_err(dev, "cannot find matching string\n");
+			kfree(esoc_prop);
+			return NULL;
+		}
+		if (strcmp(client_desc, name)) {
+			kfree(esoc_prop);
+			continue;
+		}
+		kfree(esoc_prop);
+		esoc_node = of_find_node_by_phandle(be32_to_cpup(parp));
+		esoc_clink = get_esoc_clink_by_node(esoc_node);
+		if (IS_ERR_OR_NULL(esoc_clink)) {
+			dev_err(dev, "matching esoc clink not present\n");
+			return ERR_PTR(-EPROBE_DEFER);
+		}
+		esoc_name = kasprintf(GFP_KERNEL, "esoc%d",
+							esoc_clink->id);
+		if (IS_ERR_OR_NULL(esoc_name)) {
+			dev_err(dev, "unable to allocate esoc name\n");
+			return ERR_PTR(-ENOMEM);
+		}
+		esoc_link = kasprintf(GFP_KERNEL, "%s", esoc_clink->link_name);
+		if (IS_ERR_OR_NULL(esoc_link)) {
+			dev_err(dev, "unable to allocate esoc link name\n");
+			kfree(esoc_name);
+			return ERR_PTR(-ENOMEM);
+		}
+		desc = devres_alloc(devm_esoc_desc_release,
+						sizeof(*desc), GFP_KERNEL);
+		if (IS_ERR_OR_NULL(desc)) {
+			kfree(esoc_name);
+			kfree(esoc_link);
+			dev_err(dev, "unable to allocate esoc descriptor\n");
+			return ERR_PTR(-ENOMEM);
+		}
+		desc->name = esoc_name;
+		desc->link = esoc_link;
+		desc->priv = esoc_clink;
+		devres_add(dev, desc);
+		return desc;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(devm_register_esoc_client);
+
+void devm_unregister_esoc_client(struct device *dev,
+					struct esoc_desc *esoc_desc)
+{
+	int ret;
+
+	ret = devres_release(dev, devm_esoc_desc_release,
+				devm_esoc_desc_match, esoc_desc);
+	WARN_ON(ret);
+}
+EXPORT_SYMBOL(devm_unregister_esoc_client);
+
+int esoc_register_client_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&client_notify, nb);
+}
+EXPORT_SYMBOL(esoc_register_client_notifier);
+
+void notify_esoc_clients(struct esoc_clink *esoc_clink, unsigned long evt)
+{
+	unsigned int id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&notify_lock, flags);
+	id = esoc_clink->id;
+	atomic_notifier_call_chain(&client_notify, evt, &id);
+	spin_unlock_irqrestore(&notify_lock, flags);
+}
+EXPORT_SYMBOL(notify_esoc_clients);