S:     Maintained
 F:     arch/arm/mach-ep93xx/micro9.c
 
+ARM/CORESIGHT FRAMEWORK AND DRIVERS
+M:     Mathieu Poirier <mathieu.poirier@linaro.org>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/coresight/*
+F:     Documentation/trace/coresight.txt
+F:     Documentation/devicetree/bindings/arm/coresight.txt
+
 ARM/CORGI MACHINE SUPPORT
 M:     Richard Purdie <rpurdie@rpsys.net>
 S:     Maintained
 
          against certain classes of kernel exploits.
          If in doubt, say "N".
 
+menuconfig CORESIGHT
+       bool "CoreSight Tracing Support"
+       select ARM_AMBA
+       help
+         This framework provides a kernel interface for the CoreSight debug
+         and trace drivers to register themselves with. It's intended to build
+         a topological view of the CoreSight components based on a DT
+         specification and configure the right serie of components when a
+         trace source gets enabled.
 endmenu
 
 obj-$(CONFIG_MCB)              += mcb/
 obj-$(CONFIG_RAS)              += ras/
 obj-$(CONFIG_THUNDERBOLT)      += thunderbolt/
+obj-$(CONFIG_CORESIGHT)                += coresight/
 
 
                amba_put_disable_pclk(dev);
 
-               if (cid == AMBA_CID)
+               if (cid == AMBA_CID || cid == CORESIGHT_CID)
                        dev->periphid = pid;
 
                if (!dev->periphid)
 
--- /dev/null
+#
+# Makefile for CoreSight drivers.
+#
+obj-$(CONFIG_CORESIGHT) += coresight.o
+obj-$(CONFIG_OF) += of_coresight.o
 
--- /dev/null
+/* Copyright (c) 2011-2012, 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.
+ */
+
+#ifndef _CORESIGHT_PRIV_H
+#define _CORESIGHT_PRIV_H
+
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/coresight.h>
+
+/*
+ * Coresight management registers (0xf00-0xfcc)
+ * 0xfa0 - 0xfa4: Management   registers in PFTv1.0
+ *               Trace         registers in PFTv1.1
+ */
+#define CORESIGHT_ITCTRL       0xf00
+#define CORESIGHT_CLAIMSET     0xfa0
+#define CORESIGHT_CLAIMCLR     0xfa4
+#define CORESIGHT_LAR          0xfb0
+#define CORESIGHT_LSR          0xfb4
+#define CORESIGHT_AUTHSTATUS   0xfb8
+#define CORESIGHT_DEVID                0xfc8
+#define CORESIGHT_DEVTYPE      0xfcc
+
+#define TIMEOUT_US             100
+#define BMVAL(val, lsb, msb)   ((val & GENMASK(msb, lsb)) >> lsb)
+
+static inline void CS_LOCK(void __iomem *addr)
+{
+       do {
+               /* Wait for things to settle */
+               mb();
+               writel_relaxed(0x0, addr + CORESIGHT_LAR);
+       } while (0);
+}
+
+static inline void CS_UNLOCK(void __iomem *addr)
+{
+       do {
+               writel_relaxed(CORESIGHT_UNLOCK, addr + CORESIGHT_LAR);
+               /* Make sure eveyone has seen this */
+               mb();
+       } while (0);
+}
+
+#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
+extern int etm_readl_cp14(u32 off, unsigned int *val);
+extern int etm_writel_cp14(u32 off, u32 val);
+#else
+static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
+static inline int etm_writel_cp14(u32 val, u32 off) { return 0; }
+#endif
+
+#endif
 
--- /dev/null
+/* Copyright (c) 2012, 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+#include <linux/of_platform.h>
+#include <linux/delay.h>
+
+#include "coresight-priv.h"
+
+static DEFINE_MUTEX(coresight_mutex);
+
+static int coresight_id_match(struct device *dev, void *data)
+{
+       int trace_id, i_trace_id;
+       struct coresight_device *csdev, *i_csdev;
+
+       csdev = data;
+       i_csdev = to_coresight_device(dev);
+
+       /*
+        * No need to care about oneself and components that are not
+        * sources or not enabled
+        */
+       if (i_csdev == csdev || !i_csdev->enable ||
+           i_csdev->type != CORESIGHT_DEV_TYPE_SOURCE)
+               return 0;
+
+       /* Get the source ID for both compoment */
+       trace_id = source_ops(csdev)->trace_id(csdev);
+       i_trace_id = source_ops(i_csdev)->trace_id(i_csdev);
+
+       /* All you need is one */
+       if (trace_id == i_trace_id)
+               return 1;
+
+       return 0;
+}
+
+static int coresight_source_is_unique(struct coresight_device *csdev)
+{
+       int trace_id = source_ops(csdev)->trace_id(csdev);
+
+       /* this shouldn't happen */
+       if (trace_id < 0)
+               return 0;
+
+       return !bus_for_each_dev(&coresight_bustype, NULL,
+                                csdev, coresight_id_match);
+}
+
+static int coresight_find_link_inport(struct coresight_device *csdev)
+{
+       int i;
+       struct coresight_device *parent;
+       struct coresight_connection *conn;
+
+       parent = container_of(csdev->path_link.next,
+                             struct coresight_device, path_link);
+
+       for (i = 0; i < parent->nr_outport; i++) {
+               conn = &parent->conns[i];
+               if (conn->child_dev == csdev)
+                       return conn->child_port;
+       }
+
+       dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n",
+               dev_name(&parent->dev), dev_name(&csdev->dev));
+
+       return 0;
+}
+
+static int coresight_find_link_outport(struct coresight_device *csdev)
+{
+       int i;
+       struct coresight_device *child;
+       struct coresight_connection *conn;
+
+       child = container_of(csdev->path_link.prev,
+                            struct coresight_device, path_link);
+
+       for (i = 0; i < csdev->nr_outport; i++) {
+               conn = &csdev->conns[i];
+               if (conn->child_dev == child)
+                       return conn->outport;
+       }
+
+       dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n",
+               dev_name(&csdev->dev), dev_name(&child->dev));
+
+       return 0;
+}
+
+static int coresight_enable_sink(struct coresight_device *csdev)
+{
+       int ret;
+
+       if (!csdev->enable) {
+               if (sink_ops(csdev)->enable) {
+                       ret = sink_ops(csdev)->enable(csdev);
+                       if (ret)
+                               return ret;
+               }
+               csdev->enable = true;
+       }
+
+       atomic_inc(csdev->refcnt);
+
+       return 0;
+}
+
+static void coresight_disable_sink(struct coresight_device *csdev)
+{
+       if (atomic_dec_return(csdev->refcnt) == 0) {
+               if (sink_ops(csdev)->disable) {
+                       sink_ops(csdev)->disable(csdev);
+                       csdev->enable = false;
+               }
+       }
+}
+
+static int coresight_enable_link(struct coresight_device *csdev)
+{
+       int ret;
+       int link_subtype;
+       int refport, inport, outport;
+
+       inport = coresight_find_link_inport(csdev);
+       outport = coresight_find_link_outport(csdev);
+       link_subtype = csdev->subtype.link_subtype;
+
+       if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
+               refport = inport;
+       else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
+               refport = outport;
+       else
+               refport = 0;
+
+       if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
+               if (link_ops(csdev)->enable) {
+                       ret = link_ops(csdev)->enable(csdev, inport, outport);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       csdev->enable = true;
+
+       return 0;
+}
+
+static void coresight_disable_link(struct coresight_device *csdev)
+{
+       int i, nr_conns;
+       int link_subtype;
+       int refport, inport, outport;
+
+       inport = coresight_find_link_inport(csdev);
+       outport = coresight_find_link_outport(csdev);
+       link_subtype = csdev->subtype.link_subtype;
+
+       if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
+               refport = inport;
+               nr_conns = csdev->nr_inport;
+       } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
+               refport = outport;
+               nr_conns = csdev->nr_outport;
+       } else {
+               refport = 0;
+               nr_conns = 1;
+       }
+
+       if (atomic_dec_return(&csdev->refcnt[refport]) == 0) {
+               if (link_ops(csdev)->disable)
+                       link_ops(csdev)->disable(csdev, inport, outport);
+       }
+
+       for (i = 0; i < nr_conns; i++)
+               if (atomic_read(&csdev->refcnt[i]) != 0)
+                       return;
+
+       csdev->enable = false;
+}
+
+static int coresight_enable_source(struct coresight_device *csdev)
+{
+       int ret;
+
+       if (!coresight_source_is_unique(csdev)) {
+               dev_warn(&csdev->dev, "traceID %d not unique\n",
+                        source_ops(csdev)->trace_id(csdev));
+               return -EINVAL;
+       }
+
+       if (!csdev->enable) {
+               if (source_ops(csdev)->enable) {
+                       ret = source_ops(csdev)->enable(csdev);
+                       if (ret)
+                               return ret;
+               }
+               csdev->enable = true;
+       }
+
+       atomic_inc(csdev->refcnt);
+
+       return 0;
+}
+
+static void coresight_disable_source(struct coresight_device *csdev)
+{
+       if (atomic_dec_return(csdev->refcnt) == 0) {
+               if (source_ops(csdev)->disable) {
+                       source_ops(csdev)->disable(csdev);
+                       csdev->enable = false;
+               }
+       }
+}
+
+static int coresight_enable_path(struct list_head *path)
+{
+       int ret = 0;
+       struct coresight_device *cd;
+
+       list_for_each_entry(cd, path, path_link) {
+               if (cd == list_first_entry(path, struct coresight_device,
+                                          path_link)) {
+                       ret = coresight_enable_sink(cd);
+               } else if (list_is_last(&cd->path_link, path)) {
+                       /*
+                        * Don't enable the source just yet - this needs to
+                        * happen at the very end when all links and sink
+                        * along the path have been configured properly.
+                        */
+                       ;
+               } else {
+                       ret = coresight_enable_link(cd);
+               }
+               if (ret)
+                       goto err;
+       }
+
+       return 0;
+err:
+       list_for_each_entry_continue_reverse(cd, path, path_link) {
+               if (cd == list_first_entry(path, struct coresight_device,
+                                          path_link)) {
+                       coresight_disable_sink(cd);
+               } else if (list_is_last(&cd->path_link, path)) {
+                       ;
+               } else {
+                       coresight_disable_link(cd);
+               }
+       }
+
+       return ret;
+}
+
+static int coresight_disable_path(struct list_head *path)
+{
+       struct coresight_device *cd;
+
+       list_for_each_entry_reverse(cd, path, path_link) {
+               if (cd == list_first_entry(path, struct coresight_device,
+                                          path_link)) {
+                       coresight_disable_sink(cd);
+               } else if (list_is_last(&cd->path_link, path)) {
+                       /*
+                        * The source has already been stopped, no need
+                        * to do it again here.
+                        */
+                       ;
+               } else {
+                       coresight_disable_link(cd);
+               }
+       }
+
+       return 0;
+}
+
+static int coresight_build_paths(struct coresight_device *csdev,
+                                struct list_head *path,
+                                bool enable)
+{
+       int i, ret = -EINVAL;
+       struct coresight_connection *conn;
+
+       list_add(&csdev->path_link, path);
+
+       if (csdev->type == CORESIGHT_DEV_TYPE_SINK && csdev->activated) {
+               if (enable)
+                       ret = coresight_enable_path(path);
+               else
+                       ret = coresight_disable_path(path);
+       } else {
+               for (i = 0; i < csdev->nr_outport; i++) {
+                       conn = &csdev->conns[i];
+                       if (coresight_build_paths(conn->child_dev,
+                                                   path, enable) == 0)
+                               ret = 0;
+               }
+       }
+
+       if (list_first_entry(path, struct coresight_device, path_link) != csdev)
+               dev_err(&csdev->dev, "wrong device in %s\n", __func__);
+
+       list_del(&csdev->path_link);
+
+       return ret;
+}
+
+int coresight_enable(struct coresight_device *csdev)
+{
+       int ret = 0;
+       LIST_HEAD(path);
+
+       mutex_lock(&coresight_mutex);
+       if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
+               ret = -EINVAL;
+               dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
+               goto out;
+       }
+       if (csdev->enable)
+               goto out;
+
+       if (coresight_build_paths(csdev, &path, true)) {
+               dev_err(&csdev->dev, "building path(s) failed\n");
+               goto out;
+       }
+
+       if (coresight_enable_source(csdev))
+               dev_err(&csdev->dev, "source enable failed\n");
+out:
+       mutex_unlock(&coresight_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(coresight_enable);
+
+void coresight_disable(struct coresight_device *csdev)
+{
+       LIST_HEAD(path);
+
+       mutex_lock(&coresight_mutex);
+       if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
+               dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
+               goto out;
+       }
+       if (!csdev->enable)
+               goto out;
+
+       coresight_disable_source(csdev);
+       if (coresight_build_paths(csdev, &path, false))
+               dev_err(&csdev->dev, "releasing path(s) failed\n");
+
+out:
+       mutex_unlock(&coresight_mutex);
+}
+EXPORT_SYMBOL_GPL(coresight_disable);
+
+static ssize_t enable_sink_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->activated);
+}
+
+static ssize_t enable_sink_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       ret = kstrtoul(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       if (val)
+               csdev->activated = true;
+       else
+               csdev->activated = false;
+
+       return size;
+
+}
+static DEVICE_ATTR_RW(enable_sink);
+
+static ssize_t enable_source_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable);
+}
+
+static ssize_t enable_source_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t size)
+{
+       int ret = 0;
+       unsigned long val;
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       ret = kstrtoul(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       if (val) {
+               ret = coresight_enable(csdev);
+               if (ret)
+                       return ret;
+       } else {
+               coresight_disable(csdev);
+       }
+
+       return size;
+}
+static DEVICE_ATTR_RW(enable_source);
+
+static struct attribute *coresight_sink_attrs[] = {
+       &dev_attr_enable_sink.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_sink);
+
+static struct attribute *coresight_source_attrs[] = {
+       &dev_attr_enable_source.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_source);
+
+static struct device_type coresight_dev_type[] = {
+       {
+               .name = "none",
+       },
+       {
+               .name = "sink",
+               .groups = coresight_sink_groups,
+       },
+       {
+               .name = "link",
+       },
+       {
+               .name = "linksink",
+               .groups = coresight_sink_groups,
+       },
+       {
+               .name = "source",
+               .groups = coresight_source_groups,
+       },
+};
+
+static void coresight_device_release(struct device *dev)
+{
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       kfree(csdev);
+}
+
+static int coresight_orphan_match(struct device *dev, void *data)
+{
+       int i;
+       bool still_orphan = false;
+       struct coresight_device *csdev, *i_csdev;
+       struct coresight_connection *conn;
+
+       csdev = data;
+       i_csdev = to_coresight_device(dev);
+
+       /* No need to check oneself */
+       if (csdev == i_csdev)
+               return 0;
+
+       /* Move on to another component if no connection is orphan */
+       if (!i_csdev->orphan)
+               return 0;
+       /*
+        * Circle throuch all the connection of that component.  If we find
+        * an orphan connection whose name matches @csdev, link it.
+        */
+       for (i = 0; i < i_csdev->nr_outport; i++)       {
+               conn = &i_csdev->conns[i];
+
+               /* We have found at least one orphan connection */
+               if (conn->child_dev == NULL) {
+                       /* Does it match this newly added device? */
+                       if (!strcmp(dev_name(&csdev->dev), conn->child_name))
+                               conn->child_dev = csdev;
+               } else {
+                       /* Too bad, this component still has an orphan */
+                       still_orphan = true;
+               }
+       }
+
+       i_csdev->orphan = still_orphan;
+
+       /*
+        * Returning '0' ensures that all known component on the
+        * bus will be checked.
+        */
+       return 0;
+}
+
+static void coresight_fixup_orphan_conns(struct coresight_device *csdev)
+{
+       /*
+        * No need to check for a return value as orphan connection(s)
+        * are hooked-up with each newly added component.
+        */
+       bus_for_each_dev(&coresight_bustype, NULL,
+                                csdev, coresight_orphan_match);
+}
+
+
+static int coresight_name_match(struct device *dev, void *data)
+{
+       char *to_match;
+       struct coresight_device *i_csdev;
+
+       to_match = data;
+       i_csdev = to_coresight_device(dev);
+
+       if (!strcmp(to_match, dev_name(&i_csdev->dev)))
+               return 1;
+
+       return 0;
+}
+
+static void coresight_fixup_device_conns(struct coresight_device *csdev)
+{
+       int i;
+       struct device *dev = NULL;
+       struct coresight_connection *conn;
+
+       for (i = 0; i < csdev->nr_outport; i++) {
+               conn = &csdev->conns[i];
+               dev = bus_find_device(&coresight_bustype, NULL,
+                                     (void *)conn->child_name,
+                                     coresight_name_match);
+
+               if (dev) {
+                       conn->child_dev = to_coresight_device(dev);
+               } else {
+                       csdev->orphan = true;
+                       conn->child_dev = NULL;
+               }
+       }
+}
+
+/**
+ * coresight_timeout - loop until a bit has changed to a specific state.
+ * @addr: base address of the area of interest.
+ * @offset: address of a register, starting from @addr.
+ * @position: the position of the bit of interest.
+ * @value: the value the bit should have.
+ *
+ * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
+ * TIMEOUT_US has elapsed, which ever happens first.
+ */
+
+int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
+{
+       int i;
+       u32 val;
+
+       for (i = TIMEOUT_US; i > 0; i--) {
+               val = __raw_readl(addr + offset);
+               /* waiting on the bit to go from 0 to 1 */
+               if (value) {
+                       if (val & BIT(position))
+                               return 0;
+               /* waiting on the bit to go from 1 to 0 */
+               } else {
+                       if (!(val & BIT(position)))
+                               return 0;
+               }
+
+               /*
+                * Delay is arbitrary - the specification doesn't say how long
+                * we are expected to wait.  Extra check required to make sure
+                * we don't wait needlessly on the last iteration.
+                */
+               if (i - 1)
+                       udelay(1);
+       }
+
+       return -EAGAIN;
+}
+
+struct bus_type coresight_bustype = {
+       .name   = "coresight",
+};
+
+static int __init coresight_init(void)
+{
+       return bus_register(&coresight_bustype);
+}
+postcore_initcall(coresight_init);
+
+struct coresight_device *coresight_register(struct coresight_desc *desc)
+{
+       int i;
+       int ret;
+       int link_subtype;
+       int nr_refcnts = 1;
+       atomic_t *refcnts = NULL;
+       struct coresight_device *csdev;
+       struct coresight_connection *conns;
+
+       csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
+       if (!csdev) {
+               ret = -ENOMEM;
+               goto err_kzalloc_csdev;
+       }
+
+       if (desc->type == CORESIGHT_DEV_TYPE_LINK ||
+           desc->type == CORESIGHT_DEV_TYPE_LINKSINK) {
+               link_subtype = desc->subtype.link_subtype;
+
+               if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
+                       nr_refcnts = desc->pdata->nr_inport;
+               else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
+                       nr_refcnts = desc->pdata->nr_outport;
+       }
+
+       refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
+       if (!refcnts) {
+               ret = -ENOMEM;
+               goto err_kzalloc_refcnts;
+       }
+
+       csdev->refcnt = refcnts;
+
+       csdev->nr_inport = desc->pdata->nr_inport;
+       csdev->nr_outport = desc->pdata->nr_outport;
+       conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
+       if (!conns) {
+               ret = -ENOMEM;
+               goto err_kzalloc_conns;
+       }
+
+       for (i = 0; i < csdev->nr_outport; i++) {
+               conns[i].outport = desc->pdata->outports[i];
+               conns[i].child_name = desc->pdata->child_names[i];
+               conns[i].child_port = desc->pdata->child_ports[i];
+       }
+
+       csdev->conns = conns;
+
+       csdev->type = desc->type;
+       csdev->subtype = desc->subtype;
+       csdev->ops = desc->ops;
+       csdev->orphan = false;
+
+       csdev->dev.type = &coresight_dev_type[desc->type];
+       csdev->dev.groups = desc->groups;
+       csdev->dev.parent = desc->dev;
+       csdev->dev.release = coresight_device_release;
+       csdev->dev.bus = &coresight_bustype;
+       dev_set_name(&csdev->dev, "%s", desc->pdata->name);
+
+       ret = device_register(&csdev->dev);
+       if (ret)
+               goto err_device_register;
+
+       mutex_lock(&coresight_mutex);
+
+       coresight_fixup_device_conns(csdev);
+       coresight_fixup_orphan_conns(csdev);
+
+       mutex_unlock(&coresight_mutex);
+
+       return csdev;
+
+err_device_register:
+       kfree(conns);
+err_kzalloc_conns:
+       kfree(refcnts);
+err_kzalloc_refcnts:
+       kfree(csdev);
+err_kzalloc_csdev:
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(coresight_register);
+
+void coresight_unregister(struct coresight_device *csdev)
+{
+       mutex_lock(&coresight_mutex);
+
+       kfree(csdev->conns);
+       device_unregister(&csdev->dev);
+
+       mutex_unlock(&coresight_mutex);
+}
+EXPORT_SYMBOL_GPL(coresight_unregister);
+
+MODULE_LICENSE("GPL v2");
 
--- /dev/null
+/* Copyright (c) 2012, 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/module.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/coresight.h>
+#include <asm/smp_plat.h>
+
+
+static int of_dev_node_match(struct device *dev, void *data)
+{
+       return dev->of_node == data;
+}
+
+static struct device *
+of_coresight_get_endpoint_device(struct device_node *endpoint)
+{
+       struct device *dev = NULL;
+
+       /*
+        * If we have a non-configuable replicator, it will be found on the
+        * platform bus.
+        */
+       dev = bus_find_device(&platform_bus_type, NULL,
+                             endpoint, of_dev_node_match);
+       if (dev)
+               return dev;
+
+       /*
+        * We have a configurable component - circle through the AMBA bus
+        * looking for the device that matches the endpoint node.
+        */
+       return bus_find_device(&amba_bustype, NULL,
+                              endpoint, of_dev_node_match);
+}
+
+static struct device_node *of_get_coresight_endpoint(
+               const struct device_node *parent, struct device_node *prev)
+{
+       struct device_node *node = of_graph_get_next_endpoint(parent, prev);
+
+       of_node_put(prev);
+       return node;
+}
+
+static void of_coresight_get_ports(struct device_node *node,
+                                  int *nr_inport, int *nr_outport)
+{
+       struct device_node *ep = NULL;
+       int in = 0, out = 0;
+
+       do {
+               ep = of_get_coresight_endpoint(node, ep);
+               if (!ep)
+                       break;
+
+               if (of_property_read_bool(ep, "slave-mode"))
+                       in++;
+               else
+                       out++;
+
+       } while (ep);
+
+       *nr_inport = in;
+       *nr_outport = out;
+}
+
+static int of_coresight_alloc_memory(struct device *dev,
+                       struct coresight_platform_data *pdata)
+{
+       /* List of output port on this component */
+       pdata->outports = devm_kzalloc(dev, pdata->nr_outport *
+                                      sizeof(*pdata->outports),
+                                      GFP_KERNEL);
+       if (!pdata->outports)
+               return -ENOMEM;
+
+       /* Children connected to this component via @outport */
+        pdata->child_names = devm_kzalloc(dev, pdata->nr_outport *
+                                         sizeof(*pdata->child_names),
+                                         GFP_KERNEL);
+       if (!pdata->child_names)
+               return -ENOMEM;
+
+       /* Port number on the child this component is connected to */
+       pdata->child_ports = devm_kzalloc(dev, pdata->nr_outport *
+                                         sizeof(*pdata->child_ports),
+                                         GFP_KERNEL);
+       if (!pdata->child_ports)
+               return -ENOMEM;
+
+       return 0;
+}
+
+struct coresight_platform_data *of_get_coresight_platform_data(
+                               struct device *dev, struct device_node *node)
+{
+       int i = 0, ret = 0;
+       struct coresight_platform_data *pdata;
+       struct of_endpoint endpoint, rendpoint;
+       struct device *rdev;
+       struct device_node *cpu;
+       struct device_node *ep = NULL;
+       struct device_node *rparent = NULL;
+       struct device_node *rport = NULL;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return ERR_PTR(-ENOMEM);
+
+       /* Use device name as debugfs handle */
+       pdata->name = dev_name(dev);
+
+       /* Get the number of input and output port for this component */
+       of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);
+
+       if (pdata->nr_outport) {
+               ret = of_coresight_alloc_memory(dev, pdata);
+               if (ret)
+                       return ERR_PTR(ret);
+
+               /* Iterate through each port to discover topology */
+               do {
+                       /* Get a handle on a port */
+                       ep = of_get_coresight_endpoint(node, ep);
+                       if (!ep)
+                               break;
+
+                       /*
+                        * No need to deal with input ports, processing for as
+                        * processing for output ports will deal with them.
+                        */
+                       if (of_find_property(ep, "slave-mode", NULL))
+                               continue;
+
+                       /* Get a handle on the local endpoint */
+                       ret = of_graph_parse_endpoint(ep, &endpoint);
+
+                       if (ret)
+                               continue;
+
+                       /* The local out port number */
+                       pdata->outports[i] = endpoint.id;
+
+                       /*
+                        * Get a handle on the remote port and parent
+                        * attached to it.
+                        */
+                       rparent = of_graph_get_remote_port_parent(ep);
+                       rport = of_graph_get_remote_port(ep);
+
+                       if (!rparent || !rport)
+                               continue;
+
+                       if (of_graph_parse_endpoint(rport, &rendpoint))
+                               continue;
+
+                       rdev = of_coresight_get_endpoint_device(rparent);
+                       if (!dev)
+                               continue;
+
+                       pdata->child_names[i] = dev_name(rdev);
+                       pdata->child_ports[i] = rendpoint.id;
+
+                       i++;
+               } while (ep);
+       }
+
+       /* Affinity defaults to CPU0 */
+       pdata->cpu = 0;
+       cpu = of_parse_phandle(node, "cpu", 0);
+       if (cpu) {
+               const u32 *mpidr;
+               int len, index;
+
+               mpidr = of_get_property(cpu, "reg", &len);
+               if (mpidr && len == 4) {
+                       index = get_logical_index(be32_to_cpup(mpidr));
+                       if (index != -EINVAL)
+                               pdata->cpu = index;
+               }
+       }
+
+       return pdata;
+}
+EXPORT_SYMBOL_GPL(of_get_coresight_platform_data);
 
 
 #define AMBA_NR_IRQS   9
 #define AMBA_CID       0xb105f00d
+#define CORESIGHT_CID  0xb105900d
 
 struct clk;
 
 
--- /dev/null
+/* Copyright (c) 2012, 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.
+ */
+
+#ifndef _LINUX_CORESIGHT_H
+#define _LINUX_CORESIGHT_H
+
+#include <linux/device.h>
+
+/* Peripheral id registers (0xFD0-0xFEC) */
+#define CORESIGHT_PERIPHIDR4   0xfd0
+#define CORESIGHT_PERIPHIDR5   0xfd4
+#define CORESIGHT_PERIPHIDR6   0xfd8
+#define CORESIGHT_PERIPHIDR7   0xfdC
+#define CORESIGHT_PERIPHIDR0   0xfe0
+#define CORESIGHT_PERIPHIDR1   0xfe4
+#define CORESIGHT_PERIPHIDR2   0xfe8
+#define CORESIGHT_PERIPHIDR3   0xfeC
+/* Component id registers (0xFF0-0xFFC) */
+#define CORESIGHT_COMPIDR0     0xff0
+#define CORESIGHT_COMPIDR1     0xff4
+#define CORESIGHT_COMPIDR2     0xff8
+#define CORESIGHT_COMPIDR3     0xffC
+
+#define ETM_ARCH_V3_3          0x23
+#define ETM_ARCH_V3_5          0x25
+#define PFT_ARCH_V1_0          0x30
+#define PFT_ARCH_V1_1          0x31
+
+#define CORESIGHT_UNLOCK       0xc5acce55
+
+extern struct bus_type coresight_bustype;
+
+enum coresight_dev_type {
+       CORESIGHT_DEV_TYPE_NONE,
+       CORESIGHT_DEV_TYPE_SINK,
+       CORESIGHT_DEV_TYPE_LINK,
+       CORESIGHT_DEV_TYPE_LINKSINK,
+       CORESIGHT_DEV_TYPE_SOURCE,
+};
+
+enum coresight_dev_subtype_sink {
+       CORESIGHT_DEV_SUBTYPE_SINK_NONE,
+       CORESIGHT_DEV_SUBTYPE_SINK_PORT,
+       CORESIGHT_DEV_SUBTYPE_SINK_BUFFER,
+};
+
+enum coresight_dev_subtype_link {
+       CORESIGHT_DEV_SUBTYPE_LINK_NONE,
+       CORESIGHT_DEV_SUBTYPE_LINK_MERG,
+       CORESIGHT_DEV_SUBTYPE_LINK_SPLIT,
+       CORESIGHT_DEV_SUBTYPE_LINK_FIFO,
+};
+
+enum coresight_dev_subtype_source {
+       CORESIGHT_DEV_SUBTYPE_SOURCE_NONE,
+       CORESIGHT_DEV_SUBTYPE_SOURCE_PROC,
+       CORESIGHT_DEV_SUBTYPE_SOURCE_BUS,
+       CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE,
+};
+
+/**
+ * struct coresight_dev_subtype - further characterisation of a type
+ * @sink_subtype:      type of sink this component is, as defined
+                       by @coresight_dev_subtype_sink.
+ * @link_subtype:      type of link this component is, as defined
+                       by @coresight_dev_subtype_link.
+ * @source_subtype:    type of source this component is, as defined
+                       by @coresight_dev_subtype_source.
+ */
+struct coresight_dev_subtype {
+       enum coresight_dev_subtype_sink sink_subtype;
+       enum coresight_dev_subtype_link link_subtype;
+       enum coresight_dev_subtype_source source_subtype;
+};
+
+/**
+ * struct coresight_platform_data - data harvested from the DT specification
+ * @cpu:       the CPU a source belongs to. Only applicable for ETM/PTMs.
+ * @name:      name of the component as shown under sysfs.
+ * @nr_inport: number of input ports for this component.
+ * @outports:  list of remote enpoint port number.
+ * @child_names:name of all child components connected to this device.
+ * @child_ports:child component port number the current component is
+               connected  to.
+ * @nr_outport:        number of output ports for this component.
+ * @clk:       The clock this component is associated to.
+ */
+struct coresight_platform_data {
+       int cpu;
+       const char *name;
+       int nr_inport;
+       int *outports;
+       const char **child_names;
+       int *child_ports;
+       int nr_outport;
+       struct clk *clk;
+};
+
+/**
+ * struct coresight_desc - description of a component required from drivers
+ * @type:      as defined by @coresight_dev_type.
+ * @subtype:   as defined by @coresight_dev_subtype.
+ * @ops:       generic operations for this component, as defined
+               by @coresight_ops.
+ * @pdata:     platform data collected from DT.
+ * @dev:       The device entity associated to this component.
+ * @groups     :operations specific to this component. These will end up
+               in the component's sysfs sub-directory.
+ */
+struct coresight_desc {
+       enum coresight_dev_type type;
+       struct coresight_dev_subtype subtype;
+       const struct coresight_ops *ops;
+       struct coresight_platform_data *pdata;
+       struct device *dev;
+       const struct attribute_group **groups;
+};
+
+/**
+ * struct coresight_connection - representation of a single connection
+ * @ref_count: keeping count a port' references.
+ * @outport:   a connection's output port number.
+ * @chid_name: remote component's name.
+ * @child_port:        remote component's port number @output is connected to.
+ * @child_dev: a @coresight_device representation of the component
+               connected to @outport.
+ */
+struct coresight_connection {
+       int outport;
+       const char *child_name;
+       int child_port;
+       struct coresight_device *child_dev;
+};
+
+/**
+ * struct coresight_device - representation of a device as used by the framework
+ * @nr_inport: number of input port associated to this component.
+ * @nr_outport:        number of output port associated to this component.
+ * @type:      as defined by @coresight_dev_type.
+ * @subtype:   as defined by @coresight_dev_subtype.
+ * @ops:       generic operations for this component, as defined
+               by @coresight_ops.
+ * @dev:       The device entity associated to this component.
+ * @refcnt:    keep track of what is in use.
+ * @path_link: link of current component into the path being enabled.
+ * @orphan:    true if the component has connections that haven't been linked.
+ * @enable:    'true' if component is currently part of an active path.
+ * @activated: 'true' only if a _sink_ has been activated.  A sink can be
+               activated but not yet enabled.  Enabling for a _sink_
+               happens when a source has been selected for that it.
+ */
+struct coresight_device {
+       struct coresight_connection *conns;
+       int nr_inport;
+       int nr_outport;
+       enum coresight_dev_type type;
+       struct coresight_dev_subtype subtype;
+       const struct coresight_ops *ops;
+       struct device dev;
+       atomic_t *refcnt;
+       struct list_head path_link;
+       bool orphan;
+       bool enable;    /* true only if configured as part of a path */
+       bool activated; /* true only if a sink is part of a path */
+};
+
+#define to_coresight_device(d) container_of(d, struct coresight_device, dev)
+
+#define source_ops(csdev)      csdev->ops->source_ops
+#define sink_ops(csdev)                csdev->ops->sink_ops
+#define link_ops(csdev)                csdev->ops->link_ops
+
+#define CORESIGHT_DEBUGFS_ENTRY(__name, __entry_name,                  \
+                                __mode, __get, __set, __fmt)           \
+DEFINE_SIMPLE_ATTRIBUTE(__name ## _ops, __get, __set, __fmt);          \
+static const struct coresight_ops_entry __name ## _entry = {           \
+       .name = __entry_name,                                           \
+       .mode = __mode,                                                 \
+       .ops  = &__name ## _ops                                         \
+}
+
+/**
+ * struct coresight_ops_sink - basic operations for a sink
+ * Operations available for sinks
+ * @enable:    enables the sink.
+ * @disable:   disables the sink.
+ */
+struct coresight_ops_sink {
+       int (*enable)(struct coresight_device *csdev);
+       void (*disable)(struct coresight_device *csdev);
+};
+
+/**
+ * struct coresight_ops_link - basic operations for a link
+ * Operations available for links.
+ * @enable:    enables flow between iport and oport.
+ * @disable:   disables flow between iport and oport.
+ */
+struct coresight_ops_link {
+       int (*enable)(struct coresight_device *csdev, int iport, int oport);
+       void (*disable)(struct coresight_device *csdev, int iport, int oport);
+};
+
+/**
+ * struct coresight_ops_source - basic operations for a source
+ * Operations available for sources.
+ * @trace_id:  returns the value of the component's trace ID as known
+               to the HW.
+ * @enable:    enables tracing from a source.
+ * @disable:   disables tracing for a source.
+ */
+struct coresight_ops_source {
+       int (*trace_id)(struct coresight_device *csdev);
+       int (*enable)(struct coresight_device *csdev);
+       void (*disable)(struct coresight_device *csdev);
+};
+
+struct coresight_ops {
+       const struct coresight_ops_sink *sink_ops;
+       const struct coresight_ops_link *link_ops;
+       const struct coresight_ops_source *source_ops;
+};
+
+#ifdef CONFIG_CORESIGHT
+extern struct coresight_device *
+coresight_register(struct coresight_desc *desc);
+extern void coresight_unregister(struct coresight_device *csdev);
+extern int coresight_enable(struct coresight_device *csdev);
+extern void coresight_disable(struct coresight_device *csdev);
+extern int coresight_is_bit_set(u32 val, int position, int value);
+extern int coresight_timeout(void __iomem *addr, u32 offset,
+                            int position, int value);
+#ifdef CONFIG_OF
+extern struct coresight_platform_data *of_get_coresight_platform_data(
+                               struct device *dev, struct device_node *node);
+#endif
+#else
+static inline struct coresight_device *
+coresight_register(struct coresight_desc *desc) { return NULL; }
+static inline void coresight_unregister(struct coresight_device *csdev) {}
+static inline int
+coresight_enable(struct coresight_device *csdev) { return -ENOSYS; }
+static inline void coresight_disable(struct coresight_device *csdev) {}
+static inline int coresight_is_bit_set(u32 val, int position, int value)
+                                        { return 0; }
+static inline int coresight_timeout(void __iomem *addr, u32 offset,
+                                    int position, int value) { return 1; }
+#ifdef CONFIG_OF
+static inline struct coresight_platform_data *of_get_coresight_platform_data(
+       struct device *dev, struct device_node *node) { return NULL; }
+#endif
+#endif
+
+#endif