deleted file mode 100644
@@ -1,153 +0,0 @@
-#ifndef __ASMARM_CTI_H
-#define __ASMARM_CTI_H
-
-#include <asm/io.h>
-#include <asm/hardware/coresight.h>
-
-/* The registers' definition is from section 3.2 of
- * Embedded Cross Trigger Revision: r0p0
- */
-#define CTICONTROL 0x000
-#define CTISTATUS 0x004
-#define CTILOCK 0x008
-#define CTIPROTECTION 0x00C
-#define CTIINTACK 0x010
-#define CTIAPPSET 0x014
-#define CTIAPPCLEAR 0x018
-#define CTIAPPPULSE 0x01c
-#define CTIINEN 0x020
-#define CTIOUTEN 0x0A0
-#define CTITRIGINSTATUS 0x130
-#define CTITRIGOUTSTATUS 0x134
-#define CTICHINSTATUS 0x138
-#define CTICHOUTSTATUS 0x13c
-#define CTIPERIPHID0 0xFE0
-#define CTIPERIPHID1 0xFE4
-#define CTIPERIPHID2 0xFE8
-#define CTIPERIPHID3 0xFEC
-#define CTIPCELLID0 0xFF0
-#define CTIPCELLID1 0xFF4
-#define CTIPCELLID2 0xFF8
-#define CTIPCELLID3 0xFFC
-
-/**
- * struct cti - cross trigger interface struct
- * @base: mapped virtual address for the cti base
- * @irq: irq number for the cti
- * @trig_out_for_irq: triger out number which will cause
- * the @irq happen
- *
- * cti struct used to operate cti registers.
- */
-struct cti {
- void __iomem *base;
- int irq;
- int trig_out_for_irq;
-};
-
-/**
- * cti_init - initialize the cti instance
- * @cti: cti instance
- * @base: mapped virtual address for the cti base
- * @irq: irq number for the cti
- * @trig_out: triger out number which will cause
- * the @irq happen
- *
- * called by machine code to pass the board dependent
- * @base, @irq and @trig_out to cti.
- */
-static inline void cti_init(struct cti *cti,
- void __iomem *base, int irq, int trig_out)
-{
- cti->base = base;
- cti->irq = irq;
- cti->trig_out_for_irq = trig_out;
-}
-
-/**
- * cti_map_trigger - use the @chan to map @trig_in to @trig_out
- * @cti: cti instance
- * @trig_in: trigger in number
- * @trig_out: trigger out number
- * @channel: channel number
- *
- * This function maps one trigger in of @trig_in to one trigger
- * out of @trig_out using the channel @chan.
- */
-static inline void cti_map_trigger(struct cti *cti,
- int trig_in, int trig_out, int chan)
-{
- void __iomem *base = cti->base;
- unsigned long val;
-
- val = __raw_readl(base + CTIINEN + trig_in * 4);
- val |= BIT(chan);
- __raw_writel(val, base + CTIINEN + trig_in * 4);
-
- val = __raw_readl(base + CTIOUTEN + trig_out * 4);
- val |= BIT(chan);
- __raw_writel(val, base + CTIOUTEN + trig_out * 4);
-}
-
-/**
- * cti_enable - enable the cti module
- * @cti: cti instance
- *
- * enable the cti module
- */
-static inline void cti_enable(struct cti *cti)
-{
- __raw_writel(0x1, cti->base + CTICONTROL);
-}
-
-/**
- * cti_disable - disable the cti module
- * @cti: cti instance
- *
- * enable the cti module
- */
-static inline void cti_disable(struct cti *cti)
-{
- __raw_writel(0, cti->base + CTICONTROL);
-}
-
-/**
- * cti_irq_ack - clear the cti irq
- * @cti: cti instance
- *
- * clear the cti irq
- */
-static inline void cti_irq_ack(struct cti *cti)
-{
- void __iomem *base = cti->base;
- unsigned long val;
-
- val = __raw_readl(base + CTIINTACK);
- val |= BIT(cti->trig_out_for_irq);
- __raw_writel(val, base + CTIINTACK);
-}
-
-/**
- * cti_unlock - unlock cti module
- * @cti: cti instance
- *
- * unlock the cti module, or else any writes to the cti
- * module is not allowed.
- */
-static inline void cti_unlock(struct cti *cti)
-{
- coresight_unlock(cti->base);
-}
-
-/**
- * cti_lock - lock cti module
- * @cti: cti instance
- *
- * lock the cti module, so any writes to the cti
- * module will be not allowed.
- */
-static inline void cti_lock(struct cti *cti)
-{
- coresight_lock(cti->base);
-}
-#endif
@@ -2,6 +2,8 @@ menu "Device Drivers"
source "drivers/base/Kconfig"
+source "drivers/amba/Kconfig"
+
source "drivers/bus/Kconfig"
source "drivers/connector/Kconfig"
new file mode 100644
@@ -0,0 +1,20 @@
+#
+# AMBA Devices
+#
+
+menu "AMBA devices"
+
+config ARM_AMBA_CTI
+ bool "Cross-Trigger Interface"
+ depends on ARM && OF
+ select ARM_AMBA
+ help
+ The ARM Cross Trigger Interface provides a way to route events
+ between processor modules. For example, debug events from one
+ processor can be broadcasted to other processors. The events that
+ can be routed between processors are specific to the device.
+ Currently, the driver only supports looking-up the CTI hardware
+ information (base address and interrupts) from device-tree (and
+ hence, is dependent upon CONFIG_OF).
+
+endmenu
@@ -1,2 +1,3 @@
obj-$(CONFIG_ARM_AMBA) += bus.o
+obj-$(CONFIG_ARM_AMBA_CTI) += cti.o
obj-$(CONFIG_TEGRA_AHB) += tegra-ahb.o
new file mode 100644
@@ -0,0 +1,284 @@
+/*
+ * ARM Cross Trigger Interface (CTI) Driver
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Jon Hunter <jon-hunter@ti.com>
+ *
+ * Based upon CTI Helpers by Ming Lei <ming.lei@canonical.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <asm/hardware/coresight.h>
+
+#include <linux/amba/bus.h>
+#include <linux/amba/cti.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+/* The registers' definition is from section 3.2 of
+ * Embedded Cross Trigger Revision: r0p0
+ */
+#define CTICONTROL 0x000
+#define CTISTATUS 0x004
+#define CTILOCK 0x008
+#define CTIPROTECTION 0x00C
+#define CTIINTACK 0x010
+#define CTIAPPSET 0x014
+#define CTIAPPCLEAR 0x018
+#define CTIAPPPULSE 0x01c
+#define CTIINEN 0x020
+#define CTIOUTEN 0x0A0
+#define CTITRIGINSTATUS 0x130
+#define CTITRIGOUTSTATUS 0x134
+#define CTICHINSTATUS 0x138
+#define CTICHOUTSTATUS 0x13c
+#define CTIPERIPHID0 0xFE0
+#define CTIPERIPHID1 0xFE4
+#define CTIPERIPHID2 0xFE8
+#define CTIPERIPHID3 0xFEC
+#define CTIPCELLID0 0xFF0
+#define CTIPCELLID1 0xFF4
+#define CTIPCELLID2 0xFF8
+#define CTIPCELLID3 0xFFC
+#define CTI_MAX_CHANNELS 15
+#define CTI_MAX_TRIGGERS 7
+
+#define cti_writel(v, c, x) (__raw_writel((v), (c)->base + (x)))
+#define cti_readl(c, x) (__raw_readl((c)->base + (x)))
+
+static DEFINE_SPINLOCK(cti_lock);
+static LIST_HEAD(cti_list);
+
+/**
+ * cti_map_trigger - use the @chan to map @trig_in to @trig_out
+ * @cti: CTI instance
+ * @trig_in: trigger in number
+ * @trig_out: trigger out number
+ * @chan: channel number
+ *
+ * Maps one trigger in of @trig_in to one trigger out of @trig_out
+ * using the channel @chan. The CTI module must not be enabled when
+ * calling this function.
+ */
+int cti_map_trigger(struct cti *cti, int trig_in, int trig_out, int chan)
+{
+ u32 v;
+
+ if (!cti)
+ return -EINVAL;
+
+ if (cti->enabled)
+ return -EBUSY;
+
+ if (chan > CTI_MAX_CHANNELS)
+ return -EINVAL;
+
+ if ((trig_in > CTI_MAX_TRIGGERS) || (trig_out > CTI_MAX_TRIGGERS))
+ return -EINVAL;
+
+ coresight_unlock(cti->base);
+
+ v = cti_readl(cti, CTIINEN + trig_in * 4);
+ v |= BIT(chan);
+ cti_writel(v, cti, CTIINEN + trig_in * 4);
+ v = cti_readl(cti, CTIOUTEN + trig_out * 4);
+ v |= BIT(chan);
+ cti_writel(v, cti, CTIOUTEN + trig_out * 4);
+ cti->trig_out = trig_out;
+
+ coresight_lock(cti->base);
+
+ return 0;
+}
+
+/**
+ * cti_enable - enable the CTI module
+ * @cti: CTI instance
+ *
+ * Unlocks and enables the CTI module. The CTI module cannot be
+ * programmed again until it has been disabled.
+ */
+int cti_enable(struct cti *cti)
+{
+ if (!cti || cti->enabled)
+ return -EINVAL;
+
+ coresight_unlock(cti->base);
+ cti_writel(1, cti, CTICONTROL);
+ cti->enabled = true;
+
+ return 0;
+}
+
+/**
+ * cti_disable - disable the CTI module
+ * @cti: CTI instance
+ *
+ * Disables and locks the CTI module.
+ */
+int cti_disable(struct cti *cti)
+{
+ if (!cti || !cti->enabled)
+ return -EINVAL;
+
+ cti_writel(0, cti, CTICONTROL);
+ cti->enabled = false;
+ coresight_lock(cti->base);
+
+ return 0;
+}
+
+/**
+ * cti_irq_ack - acknowledges the CTI trigger output
+ * @cti: CTI instance
+ *
+ * Acknowledges the CTI trigger output by writting to the appropriate
+ * bit in the CTI interrupt acknowledge register.
+ */
+int cti_irq_ack(struct cti *cti)
+{
+ u32 v;
+
+ if (!cti || !cti->enabled)
+ return -EINVAL;
+
+ v = cti_readl(cti, CTIINTACK);
+ v |= BIT(cti->trig_out);
+ cti_writel(v, cti, CTIINTACK);
+
+ return 0;
+}
+
+/**
+ * cti_get - acquire a CTI module
+ * @name: name of CTI instance
+ *
+ * Acquires a CTI module from a list of CTI modules by name. If the CTI
+ * module is already in use then return NULL, otherwise return a valid
+ * handle to the CTI module.
+ */
+struct cti *cti_get(const char *name)
+{
+ struct cti *cti = NULL;
+ unsigned long flags;
+
+ if (!name)
+ return NULL;
+
+ spin_lock_irqsave(&cti_lock, flags);
+
+ if (list_empty(&cti_list))
+ goto out;
+
+ list_for_each_entry(cti, &cti_list, node) {
+ if (!strcmp(cti->name, name) && (!cti->reserved)) {
+ cti->reserved = true;
+ goto out;
+ }
+ }
+
+out:
+ spin_unlock_irqrestore(&cti_lock, flags);
+
+ if (cti)
+ pm_runtime_get_sync(cti->dev);
+
+ return cti;
+}
+
+/**
+ * cti_put - release handle to CTI module
+ * @cti: CTI instance
+ *
+ * Releases a handle to CTI module that was previously acquired.
+ */
+void cti_put(struct cti *cti)
+{
+ if (!cti || !cti->reserved)
+ return;
+
+ cti->reserved = false;
+
+ pm_runtime_put(cti->dev);
+}
+
+static int cti_probe(struct amba_device *dev, const struct amba_id *id)
+{
+ struct cti *cti;
+ struct device_node *np = dev->dev.of_node;
+ int rc;
+
+ if (!np) {
+ dev_err(&dev->dev, "device-tree not found!\n");
+ return -ENODEV;
+ }
+
+ cti = devm_kzalloc(&dev->dev, sizeof(struct cti), GFP_KERNEL);
+ if (!cti) {
+ dev_err(&dev->dev, "memory allocation failed!\n");
+ return -ENOMEM;
+ }
+
+ rc = of_property_read_string_index(np, "arm,cti-name", 0, &cti->name);
+ if (rc) {
+ dev_err(&dev->dev, "no name found for CTI!\n");
+ return rc;
+ }
+
+ if (!dev->irq[0]) {
+ dev_err(&dev->dev, "no CTI interrupt found!\n");
+ return -ENODEV;
+ }
+
+ cti->irq = dev->irq[0];
+ cti->base = of_iomap(np, 0);
+ if (!cti->base) {
+ dev_err(&dev->dev, "unable to map CTI registers!\n");
+ return -ENOMEM;
+ }
+
+ cti->dev = &dev->dev;
+ amba_set_drvdata(dev, cti);
+ list_add_tail(&cti->node, &cti_list);
+
+ /*
+ * AMBA bus driver has already enabled RPM and incremented
+ * use-count, so now we can safely decrement the use-count
+ * and allow the CTI driver to manage RPM for the device.
+ */
+ pm_runtime_put(&dev->dev);
+
+ dev_info(&dev->dev, "ARM CTI driver");
+
+ return 0;
+}
+
+static const struct amba_id cti_ids[] = {
+ {
+ .id = 0x003bb906,
+ .mask = 0x00ffffff,
+ },
+ { 0, 0 },
+};
+
+static struct amba_driver cti_driver = {
+ .drv = {
+ .name = "cti",
+ },
+ .id_table = cti_ids,
+ .probe = cti_probe,
+};
+
+static int __init cti_init(void)
+{
+ return amba_driver_register(&cti_driver);
+}
+subsys_initcall(cti_init);
new file mode 100644
@@ -0,0 +1,82 @@
+/*
+ * ARM Cross Trigger Interface Platform Driver
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Jon Hunter <jon-hunter@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AMBA_CTI_H
+#define AMBA_CTI_H
+
+#include <linux/io.h>
+
+/**
+ * struct cti - Cross Trigger Interface (CTI) struct
+ *
+ * @node: Connects CTI instance to list of CTI instances
+ * @dev: Pointer to device structure
+ * @base: Mapped virtual address of the CTI module
+ * @name: Name associated with CTI instance
+ * @irq: Interrupt associated with CTI instance
+ * @trig_out: Trigger output associated with interrupt (@irq)
+ * @reserved: Used to indicate if CTI instance has been allocated
+ * @enabled: Used to indicate if CTI instance has been enabled
+ */
+struct cti {
+ struct list_head node;
+ struct device *dev;
+ void __iomem *base;
+ const char *name;
+ int irq;
+ int trig_out;
+ bool reserved;
+ bool enabled;
+};
+
+#ifdef CONFIG_ARM_AMBA_CTI
+
+int cti_map_trigger(struct cti *cti, int trig_in, int trig_out, int chan);
+int cti_enable(struct cti *cti);
+int cti_disable(struct cti *cti);
+int cti_irq_ack(struct cti *cti);
+struct cti *cti_get(const char *name);
+void cti_put(struct cti *cti);
+
+#else
+
+static inline int cti_map_trigger(struct cti *cti, int trig_in, int trig_out,
+ int chan)
+{
+ return 0;
+}
+
+static inline int cti_enable(struct cti *cti)
+{
+ return 0;
+}
+
+static inline int cti_disable(struct cti *cti)
+{
+ return 0;
+}
+
+static inline int cti_irq_ack(struct cti *cti)
+{
+ return 0;
+}
+
+static inline struct cti *cti_get(const char *name)
+{
+ return NULL;
+}
+
+static inline void cti_put(struct cti *cti) {}
+
+#endif /* ARM_AMBA_CTI */
+
+#endif /* AMBA_CTI_H */
Convert the Cross Trigger Interface (CTI) helpers in cti.h into a AMBA bus driver so that we can use device-tree to look-up the hardware specific information such as base address and interrupt number during the device probe. This also add APIs to request, cti_get() and release, cti_put(), a CTI module so that drivers can allocate a module at runtime. Currently, the driver only supports looking-up the CTI hardware information via device-tree, however, the driver could be extended to support non-device-tree configurations if needed for a particular architecture. The CTI driver only currently supports CTI modules that have a single CPU interrupt, however, could be extended in the future to support more interrupts if a device requires this. Signed-off-by: Jon Hunter <jon-hunter@ti.com> --- arch/arm/include/asm/cti.h | 153 ------------------------ drivers/Kconfig | 2 + drivers/amba/Kconfig | 20 ++++ drivers/amba/Makefile | 1 + drivers/amba/cti.c | 284 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/amba/cti.h | 82 +++++++++++++ 6 files changed, 389 insertions(+), 153 deletions(-) delete mode 100644 arch/arm/include/asm/cti.h create mode 100644 drivers/amba/Kconfig create mode 100644 drivers/amba/cti.c create mode 100644 include/linux/amba/cti.h