MALI: utgard: RK: remove core_scaling in "platform specific code"
[firefly-linux-kernel-4.4.55.git] / drivers / hwtracing / coresight / coresight-tmc.c
index a57c7ec1661f915f9d7bc680cefc3558129d299a..9e02ac963cd0e3fbb38f9ee5e3fd082719f38bf7 100644 (file)
@@ -1,4 +1,6 @@
 /* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Description: CoreSight Trace Memory Controller driver
  *
  * 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
@@ -11,7 +13,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 
 #include "coresight-priv.h"
+#include "coresight-tmc.h"
 
-#define TMC_RSZ                        0x004
-#define TMC_STS                        0x00c
-#define TMC_RRD                        0x010
-#define TMC_RRP                        0x014
-#define TMC_RWP                        0x018
-#define TMC_TRG                        0x01c
-#define TMC_CTL                        0x020
-#define TMC_RWD                        0x024
-#define TMC_MODE               0x028
-#define TMC_LBUFLEVEL          0x02c
-#define TMC_CBUFLEVEL          0x030
-#define TMC_BUFWM              0x034
-#define TMC_RRPHI              0x038
-#define TMC_RWPHI              0x03c
-#define TMC_AXICTL             0x110
-#define TMC_DBALO              0x118
-#define TMC_DBAHI              0x11c
-#define TMC_FFSR               0x300
-#define TMC_FFCR               0x304
-#define TMC_PSCR               0x308
-#define TMC_ITMISCOP0          0xee0
-#define TMC_ITTRFLIN           0xee8
-#define TMC_ITATBDATA0         0xeec
-#define TMC_ITATBCTR2          0xef0
-#define TMC_ITATBCTR1          0xef4
-#define TMC_ITATBCTR0          0xef8
-
-/* register description */
-/* TMC_CTL - 0x020 */
-#define TMC_CTL_CAPT_EN                BIT(0)
-/* TMC_STS - 0x00C */
-#define TMC_STS_TRIGGERED      BIT(1)
-/* TMC_AXICTL - 0x110 */
-#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
-#define TMC_AXICTL_PROT_CTL_B1 BIT(1)
-#define TMC_AXICTL_SCT_GAT_MODE        BIT(7)
-#define TMC_AXICTL_WR_BURST_LEN 0xF00
-/* TMC_FFCR - 0x304 */
-#define TMC_FFCR_EN_FMT                BIT(0)
-#define TMC_FFCR_EN_TI         BIT(1)
-#define TMC_FFCR_FON_FLIN      BIT(4)
-#define TMC_FFCR_FON_TRIG_EVT  BIT(5)
-#define TMC_FFCR_FLUSHMAN      BIT(6)
-#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
-#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
-
-#define TMC_STS_TRIGGERED_BIT  2
-#define TMC_FFCR_FLUSHMAN_BIT  6
-
-enum tmc_config_type {
-       TMC_CONFIG_TYPE_ETB,
-       TMC_CONFIG_TYPE_ETR,
-       TMC_CONFIG_TYPE_ETF,
-};
-
-enum tmc_mode {
-       TMC_MODE_CIRCULAR_BUFFER,
-       TMC_MODE_SOFTWARE_FIFO,
-       TMC_MODE_HARDWARE_FIFO,
-};
-
-enum tmc_mem_intf_width {
-       TMC_MEM_INTF_WIDTH_32BITS       = 0x2,
-       TMC_MEM_INTF_WIDTH_64BITS       = 0x3,
-       TMC_MEM_INTF_WIDTH_128BITS      = 0x4,
-       TMC_MEM_INTF_WIDTH_256BITS      = 0x5,
-};
-
-/**
- * struct tmc_drvdata - specifics associated to an TMC component
- * @base:      memory mapped base address for this component.
- * @dev:       the device entity associated to this component.
- * @csdev:     component vitals needed by the framework.
- * @miscdev:   specifics to handle "/dev/xyz.tmc" entry.
- * @spinlock:  only one at a time pls.
- * @read_count:        manages preparation of buffer for reading.
- * @buf:       area of memory where trace data get sent.
- * @paddr:     DMA start location in RAM.
- * @vaddr:     virtual representation of @paddr.
- * @size:      @buf size.
- * @enable:    this TMC is being used.
- * @config_type: TMC variant, must be of type @tmc_config_type.
- * @trigger_cntr: amount of words to store after a trigger.
- */
-struct tmc_drvdata {
-       void __iomem            *base;
-       struct device           *dev;
-       struct coresight_device *csdev;
-       struct miscdevice       miscdev;
-       spinlock_t              spinlock;
-       int                     read_count;
-       bool                    reading;
-       char                    *buf;
-       dma_addr_t              paddr;
-       void __iomem            *vaddr;
-       u32                     size;
-       bool                    enable;
-       enum tmc_config_type    config_type;
-       u32                     trigger_cntr;
-};
-
-static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
+void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
 {
        /* Ensure formatter, unformatter and hardware fifo are empty */
        if (coresight_timeout(drvdata->base,
-                             TMC_STS, TMC_STS_TRIGGERED_BIT, 1)) {
+                             TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
                dev_err(drvdata->dev,
                        "timeout observed when probing at offset %#x\n",
                        TMC_STS);
        }
 }
 
-static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
+void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
 {
        u32 ffcr;
 
        ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
        ffcr |= TMC_FFCR_STOP_ON_FLUSH;
        writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
-       ffcr |= TMC_FFCR_FLUSHMAN;
+       ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT);
        writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
        /* Ensure flush completes */
        if (coresight_timeout(drvdata->base,
@@ -159,343 +60,73 @@ static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
                        TMC_FFCR);
        }
 
-       tmc_wait_for_ready(drvdata);
+       tmc_wait_for_tmcready(drvdata);
 }
 
-static void tmc_enable_hw(struct tmc_drvdata *drvdata)
+void tmc_enable_hw(struct tmc_drvdata *drvdata)
 {
        writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
 }
 
-static void tmc_disable_hw(struct tmc_drvdata *drvdata)
+void tmc_disable_hw(struct tmc_drvdata *drvdata)
 {
        writel_relaxed(0x0, drvdata->base + TMC_CTL);
 }
 
-static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
-{
-       /* Zero out the memory to help with debug */
-       memset(drvdata->buf, 0, drvdata->size);
-
-       CS_UNLOCK(drvdata->base);
-
-       writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-       writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
-                      TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
-                      TMC_FFCR_TRIGON_TRIGIN,
-                      drvdata->base + TMC_FFCR);
-
-       writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
-       tmc_enable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
-{
-       u32 axictl;
-
-       /* Zero out the memory to help with debug */
-       memset(drvdata->vaddr, 0, drvdata->size);
-
-       CS_UNLOCK(drvdata->base);
-
-       writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
-       writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-
-       axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
-       axictl |= TMC_AXICTL_WR_BURST_LEN;
-       writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-       axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
-       writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-       axictl = (axictl &
-                 ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
-                 TMC_AXICTL_PROT_CTL_B1;
-       writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-
-       writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
-       writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
-       writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
-                      TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
-                      TMC_FFCR_TRIGON_TRIGIN,
-                      drvdata->base + TMC_FFCR);
-       writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
-       tmc_enable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
-
-       writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
-       writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
-                      drvdata->base + TMC_FFCR);
-       writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
-       tmc_enable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
-       unsigned long flags;
-
-       pm_runtime_get_sync(drvdata->dev);
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       if (drvdata->reading) {
-               spin_unlock_irqrestore(&drvdata->spinlock, flags);
-               pm_runtime_put(drvdata->dev);
-               return -EBUSY;
-       }
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-               tmc_etb_enable_hw(drvdata);
-       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               tmc_etr_enable_hw(drvdata);
-       } else {
-               if (mode == TMC_MODE_CIRCULAR_BUFFER)
-                       tmc_etb_enable_hw(drvdata);
-               else
-                       tmc_etf_enable_hw(drvdata);
-       }
-       drvdata->enable = true;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       dev_info(drvdata->dev, "TMC enabled\n");
-       return 0;
-}
-
-static int tmc_enable_sink(struct coresight_device *csdev)
-{
-       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static int tmc_enable_link(struct coresight_device *csdev, int inport,
-                          int outport)
+static int tmc_read_prepare(struct tmc_drvdata *drvdata)
 {
-       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
+       int ret = 0;
 
-static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
-{
-       enum tmc_mem_intf_width memwidth;
-       u8 memwords;
-       char *bufp;
-       u32 read_data;
-       int i;
-
-       memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
-       if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
-               memwords = 1;
-       else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
-               memwords = 2;
-       else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
-               memwords = 4;
-       else
-               memwords = 8;
-
-       bufp = drvdata->buf;
-       while (1) {
-               for (i = 0; i < memwords; i++) {
-                       read_data = readl_relaxed(drvdata->base + TMC_RRD);
-                       if (read_data == 0xFFFFFFFF)
-                               return;
-                       memcpy(bufp, &read_data, 4);
-                       bufp += 4;
-               }
+       switch (drvdata->config_type) {
+       case TMC_CONFIG_TYPE_ETB:
+       case TMC_CONFIG_TYPE_ETF:
+               ret = tmc_read_prepare_etb(drvdata);
+               break;
+       case TMC_CONFIG_TYPE_ETR:
+               ret = tmc_read_prepare_etr(drvdata);
+               break;
+       default:
+               ret = -EINVAL;
        }
-}
-
-static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
 
-       tmc_flush_and_stop(drvdata);
-       tmc_etb_dump_hw(drvdata);
-       tmc_disable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
+       if (!ret)
+               dev_info(drvdata->dev, "TMC read start\n");
 
-static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
-{
-       u32 rwp, val;
-
-       rwp = readl_relaxed(drvdata->base + TMC_RWP);
-       val = readl_relaxed(drvdata->base + TMC_STS);
-
-       /* How much memory do we still have */
-       if (val & BIT(0))
-               drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
-       else
-               drvdata->buf = drvdata->vaddr;
-}
-
-static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
-
-       tmc_flush_and_stop(drvdata);
-       tmc_etr_dump_hw(drvdata);
-       tmc_disable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
-
-       tmc_flush_and_stop(drvdata);
-       tmc_disable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
+       return ret;
 }
 
-static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
+static int tmc_read_unprepare(struct tmc_drvdata *drvdata)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       if (drvdata->reading)
-               goto out;
+       int ret = 0;
 
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-               tmc_etb_disable_hw(drvdata);
-       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               tmc_etr_disable_hw(drvdata);
-       } else {
-               if (mode == TMC_MODE_CIRCULAR_BUFFER)
-                       tmc_etb_disable_hw(drvdata);
-               else
-                       tmc_etf_disable_hw(drvdata);
+       switch (drvdata->config_type) {
+       case TMC_CONFIG_TYPE_ETB:
+       case TMC_CONFIG_TYPE_ETF:
+               ret = tmc_read_unprepare_etb(drvdata);
+               break;
+       case TMC_CONFIG_TYPE_ETR:
+               ret = tmc_read_unprepare_etr(drvdata);
+               break;
+       default:
+               ret = -EINVAL;
        }
-out:
-       drvdata->enable = false;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       pm_runtime_put(drvdata->dev);
 
-       dev_info(drvdata->dev, "TMC disabled\n");
-}
+       if (!ret)
+               dev_info(drvdata->dev, "TMC read end\n");
 
-static void tmc_disable_sink(struct coresight_device *csdev)
-{
-       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static void tmc_disable_link(struct coresight_device *csdev, int inport,
-                            int outport)
-{
-       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static const struct coresight_ops_sink tmc_sink_ops = {
-       .enable         = tmc_enable_sink,
-       .disable        = tmc_disable_sink,
-};
-
-static const struct coresight_ops_link tmc_link_ops = {
-       .enable         = tmc_enable_link,
-       .disable        = tmc_disable_link,
-};
-
-static const struct coresight_ops tmc_etb_cs_ops = {
-       .sink_ops       = &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etr_cs_ops = {
-       .sink_ops       = &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etf_cs_ops = {
-       .sink_ops       = &tmc_sink_ops,
-       .link_ops       = &tmc_link_ops,
-};
-
-static int tmc_read_prepare(struct tmc_drvdata *drvdata)
-{
-       int ret;
-       unsigned long flags;
-       enum tmc_mode mode;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       if (!drvdata->enable)
-               goto out;
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-               tmc_etb_disable_hw(drvdata);
-       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               tmc_etr_disable_hw(drvdata);
-       } else {
-               mode = readl_relaxed(drvdata->base + TMC_MODE);
-               if (mode == TMC_MODE_CIRCULAR_BUFFER) {
-                       tmc_etb_disable_hw(drvdata);
-               } else {
-                       ret = -ENODEV;
-                       goto err;
-               }
-       }
-out:
-       drvdata->reading = true;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       dev_info(drvdata->dev, "TMC read start\n");
-       return 0;
-err:
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
        return ret;
 }
 
-static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
-{
-       unsigned long flags;
-       enum tmc_mode mode;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       if (!drvdata->enable)
-               goto out;
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-               tmc_etb_enable_hw(drvdata);
-       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               tmc_etr_enable_hw(drvdata);
-       } else {
-               mode = readl_relaxed(drvdata->base + TMC_MODE);
-               if (mode == TMC_MODE_CIRCULAR_BUFFER)
-                       tmc_etb_enable_hw(drvdata);
-       }
-out:
-       drvdata->reading = false;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       dev_info(drvdata->dev, "TMC read end\n");
-}
-
 static int tmc_open(struct inode *inode, struct file *file)
 {
+       int ret;
        struct tmc_drvdata *drvdata = container_of(file->private_data,
                                                   struct tmc_drvdata, miscdev);
-       int ret = 0;
-
-       if (drvdata->read_count++)
-               goto out;
 
        ret = tmc_read_prepare(drvdata);
        if (ret)
                return ret;
-out:
+
        nonseekable_open(inode, file);
 
        dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
@@ -535,19 +166,14 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
 
 static int tmc_release(struct inode *inode, struct file *file)
 {
+       int ret;
        struct tmc_drvdata *drvdata = container_of(file->private_data,
                                                   struct tmc_drvdata, miscdev);
 
-       if (--drvdata->read_count) {
-               if (drvdata->read_count < 0) {
-                       dev_err(drvdata->dev, "mismatched close\n");
-                       drvdata->read_count = 0;
-               }
-               goto out;
-       }
+       ret = tmc_read_unprepare(drvdata);
+       if (ret)
+               return ret;
 
-       tmc_read_unprepare(drvdata);
-out:
        dev_dbg(drvdata->dev, "%s: released\n", __func__);
        return 0;
 }
@@ -560,56 +186,71 @@ static const struct file_operations tmc_fops = {
        .llseek         = no_llseek,
 };
 
-static ssize_t status_show(struct device *dev,
-                          struct device_attribute *attr, char *buf)
+static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid)
 {
-       unsigned long flags;
-       u32 tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg;
-       u32 tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr;
-       u32 devid;
-       struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+       enum tmc_mem_intf_width memwidth;
 
-       pm_runtime_get_sync(drvdata->dev);
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       CS_UNLOCK(drvdata->base);
-
-       tmc_rsz = readl_relaxed(drvdata->base + TMC_RSZ);
-       tmc_sts = readl_relaxed(drvdata->base + TMC_STS);
-       tmc_rrp = readl_relaxed(drvdata->base + TMC_RRP);
-       tmc_rwp = readl_relaxed(drvdata->base + TMC_RWP);
-       tmc_trg = readl_relaxed(drvdata->base + TMC_TRG);
-       tmc_ctl = readl_relaxed(drvdata->base + TMC_CTL);
-       tmc_ffsr = readl_relaxed(drvdata->base + TMC_FFSR);
-       tmc_ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
-       tmc_mode = readl_relaxed(drvdata->base + TMC_MODE);
-       tmc_pscr = readl_relaxed(drvdata->base + TMC_PSCR);
-       devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
+       /*
+        * Excerpt from the TRM:
+        *
+        * DEVID::MEMWIDTH[10:8]
+        * 0x2 Memory interface databus is 32 bits wide.
+        * 0x3 Memory interface databus is 64 bits wide.
+        * 0x4 Memory interface databus is 128 bits wide.
+        * 0x5 Memory interface databus is 256 bits wide.
+        */
+       switch (BMVAL(devid, 8, 10)) {
+       case 0x2:
+               memwidth = TMC_MEM_INTF_WIDTH_32BITS;
+               break;
+       case 0x3:
+               memwidth = TMC_MEM_INTF_WIDTH_64BITS;
+               break;
+       case 0x4:
+               memwidth = TMC_MEM_INTF_WIDTH_128BITS;
+               break;
+       case 0x5:
+               memwidth = TMC_MEM_INTF_WIDTH_256BITS;
+               break;
+       default:
+               memwidth = 0;
+       }
 
-       CS_LOCK(drvdata->base);
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-       pm_runtime_put(drvdata->dev);
-
-       return sprintf(buf,
-                      "Depth:\t\t0x%x\n"
-                      "Status:\t\t0x%x\n"
-                      "RAM read ptr:\t0x%x\n"
-                      "RAM wrt ptr:\t0x%x\n"
-                      "Trigger cnt:\t0x%x\n"
-                      "Control:\t0x%x\n"
-                      "Flush status:\t0x%x\n"
-                      "Flush ctrl:\t0x%x\n"
-                      "Mode:\t\t0x%x\n"
-                      "PSRC:\t\t0x%x\n"
-                      "DEVID:\t\t0x%x\n",
-                       tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg,
-                       tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr, devid);
-
-       return -EINVAL;
+       return memwidth;
 }
-static DEVICE_ATTR_RO(status);
 
-static ssize_t trigger_cntr_show(struct device *dev,
-                           struct device_attribute *attr, char *buf)
+#define coresight_tmc_simple_func(name, offset)                        \
+       coresight_simple_func(struct tmc_drvdata, name, offset)
+
+coresight_tmc_simple_func(rsz, TMC_RSZ);
+coresight_tmc_simple_func(sts, TMC_STS);
+coresight_tmc_simple_func(rrp, TMC_RRP);
+coresight_tmc_simple_func(rwp, TMC_RWP);
+coresight_tmc_simple_func(trg, TMC_TRG);
+coresight_tmc_simple_func(ctl, TMC_CTL);
+coresight_tmc_simple_func(ffsr, TMC_FFSR);
+coresight_tmc_simple_func(ffcr, TMC_FFCR);
+coresight_tmc_simple_func(mode, TMC_MODE);
+coresight_tmc_simple_func(pscr, TMC_PSCR);
+coresight_tmc_simple_func(devid, CORESIGHT_DEVID);
+
+static struct attribute *coresight_tmc_mgmt_attrs[] = {
+       &dev_attr_rsz.attr,
+       &dev_attr_sts.attr,
+       &dev_attr_rrp.attr,
+       &dev_attr_rwp.attr,
+       &dev_attr_trg.attr,
+       &dev_attr_ctl.attr,
+       &dev_attr_ffsr.attr,
+       &dev_attr_ffcr.attr,
+       &dev_attr_mode.attr,
+       &dev_attr_pscr.attr,
+       &dev_attr_devid.attr,
+       NULL,
+};
+
+ssize_t trigger_cntr_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
 {
        struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
        unsigned long val = drvdata->trigger_cntr;
@@ -634,26 +275,25 @@ static ssize_t trigger_cntr_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(trigger_cntr);
 
-static struct attribute *coresight_etb_attrs[] = {
+static struct attribute *coresight_tmc_attrs[] = {
        &dev_attr_trigger_cntr.attr,
-       &dev_attr_status.attr,
        NULL,
 };
-ATTRIBUTE_GROUPS(coresight_etb);
 
-static struct attribute *coresight_etr_attrs[] = {
-       &dev_attr_trigger_cntr.attr,
-       &dev_attr_status.attr,
-       NULL,
+static const struct attribute_group coresight_tmc_group = {
+       .attrs = coresight_tmc_attrs,
 };
-ATTRIBUTE_GROUPS(coresight_etr);
 
-static struct attribute *coresight_etf_attrs[] = {
-       &dev_attr_trigger_cntr.attr,
-       &dev_attr_status.attr,
+static const struct attribute_group coresight_tmc_mgmt_group = {
+       .attrs = coresight_tmc_mgmt_attrs,
+       .name = "mgmt",
+};
+
+const struct attribute_group *coresight_tmc_groups[] = {
+       &coresight_tmc_group,
+       &coresight_tmc_mgmt_group,
        NULL,
 };
-ATTRIBUTE_GROUPS(coresight_etf);
 
 static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 {
@@ -692,6 +332,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 
        devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
        drvdata->config_type = BMVAL(devid, 6, 7);
+       drvdata->memwidth = tmc_get_memwidth(devid);
 
        if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
                if (np)
@@ -706,20 +347,6 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 
        pm_runtime_put(&adev->dev);
 
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               drvdata->vaddr = dma_alloc_coherent(dev, drvdata->size,
-                                               &drvdata->paddr, GFP_KERNEL);
-               if (!drvdata->vaddr)
-                       return -ENOMEM;
-
-               memset(drvdata->vaddr, 0, drvdata->size);
-               drvdata->buf = drvdata->vaddr;
-       } else {
-               drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
-               if (!drvdata->buf)
-                       return -ENOMEM;
-       }
-
        desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
        if (!desc) {
                ret = -ENOMEM;
@@ -729,20 +356,18 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
        desc->pdata = pdata;
        desc->dev = dev;
        desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+       desc->groups = coresight_tmc_groups;
 
        if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
                desc->type = CORESIGHT_DEV_TYPE_SINK;
                desc->ops = &tmc_etb_cs_ops;
-               desc->groups = coresight_etb_groups;
        } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
                desc->type = CORESIGHT_DEV_TYPE_SINK;
                desc->ops = &tmc_etr_cs_ops;
-               desc->groups = coresight_etr_groups;
        } else {
                desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
                desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
                desc->ops = &tmc_etf_cs_ops;
-               desc->groups = coresight_etf_groups;
        }
 
        drvdata->csdev = coresight_register(desc);
@@ -758,7 +383,6 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
        if (ret)
                goto err_misc_register;
 
-       dev_info(dev, "TMC initialized\n");
        return 0;
 
 err_misc_register:
@@ -766,23 +390,10 @@ err_misc_register:
 err_devm_kzalloc:
        if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
                dma_free_coherent(dev, drvdata->size,
-                               &drvdata->paddr, GFP_KERNEL);
+                               drvdata->vaddr, drvdata->paddr);
        return ret;
 }
 
-static int tmc_remove(struct amba_device *adev)
-{
-       struct tmc_drvdata *drvdata = amba_get_drvdata(adev);
-
-       misc_deregister(&drvdata->miscdev);
-       coresight_unregister(drvdata->csdev);
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
-               dma_free_coherent(drvdata->dev, drvdata->size,
-                                 &drvdata->paddr, GFP_KERNEL);
-
-       return 0;
-}
-
 static struct amba_id tmc_ids[] = {
        {
                .id     = 0x0003b961,
@@ -795,13 +406,9 @@ static struct amba_driver tmc_driver = {
        .drv = {
                .name   = "coresight-tmc",
                .owner  = THIS_MODULE,
+               .suppress_bind_attrs = true,
        },
        .probe          = tmc_probe,
-       .remove         = tmc_remove,
        .id_table       = tmc_ids,
 };
-
-module_amba_driver(tmc_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Trace Memory Controller driver");
+builtin_amba_driver(tmc_driver);