root/drivers/hwtracing/coresight/coresight-replicator.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dynamic_replicator_reset
  2. replicator_reset
  3. dynamic_replicator_enable
  4. replicator_enable
  5. dynamic_replicator_disable
  6. replicator_disable
  7. replicator_probe
  8. static_replicator_probe
  9. replicator_runtime_suspend
  10. replicator_runtime_resume
  11. dynamic_replicator_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
   4  *
   5  * Description: CoreSight Replicator driver
   6  */
   7 
   8 #include <linux/acpi.h>
   9 #include <linux/amba/bus.h>
  10 #include <linux/kernel.h>
  11 #include <linux/device.h>
  12 #include <linux/platform_device.h>
  13 #include <linux/io.h>
  14 #include <linux/err.h>
  15 #include <linux/slab.h>
  16 #include <linux/pm_runtime.h>
  17 #include <linux/clk.h>
  18 #include <linux/of.h>
  19 #include <linux/coresight.h>
  20 
  21 #include "coresight-priv.h"
  22 
  23 #define REPLICATOR_IDFILTER0            0x000
  24 #define REPLICATOR_IDFILTER1            0x004
  25 
  26 DEFINE_CORESIGHT_DEVLIST(replicator_devs, "replicator");
  27 
  28 /**
  29  * struct replicator_drvdata - specifics associated to a replicator component
  30  * @base:       memory mapped base address for this component. Also indicates
  31  *              whether this one is programmable or not.
  32  * @atclk:      optional clock for the core parts of the replicator.
  33  * @csdev:      component vitals needed by the framework
  34  * @spinlock:   serialize enable/disable operations.
  35  */
  36 struct replicator_drvdata {
  37         void __iomem            *base;
  38         struct clk              *atclk;
  39         struct coresight_device *csdev;
  40         spinlock_t              spinlock;
  41 };
  42 
  43 static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
  44 {
  45         CS_UNLOCK(drvdata->base);
  46 
  47         if (!coresight_claim_device_unlocked(drvdata->base)) {
  48                 writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0);
  49                 writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1);
  50                 coresight_disclaim_device_unlocked(drvdata->base);
  51         }
  52 
  53         CS_LOCK(drvdata->base);
  54 }
  55 
  56 /*
  57  * replicator_reset : Reset the replicator configuration to sane values.
  58  */
  59 static inline void replicator_reset(struct replicator_drvdata *drvdata)
  60 {
  61         if (drvdata->base)
  62                 dynamic_replicator_reset(drvdata);
  63 }
  64 
  65 static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
  66                                      int inport, int outport)
  67 {
  68         int rc = 0;
  69         u32 reg;
  70 
  71         switch (outport) {
  72         case 0:
  73                 reg = REPLICATOR_IDFILTER0;
  74                 break;
  75         case 1:
  76                 reg = REPLICATOR_IDFILTER1;
  77                 break;
  78         default:
  79                 WARN_ON(1);
  80                 return -EINVAL;
  81         }
  82 
  83         CS_UNLOCK(drvdata->base);
  84 
  85         if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) &&
  86             (readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff))
  87                 rc = coresight_claim_device_unlocked(drvdata->base);
  88 
  89         /* Ensure that the outport is enabled. */
  90         if (!rc)
  91                 writel_relaxed(0x00, drvdata->base + reg);
  92         CS_LOCK(drvdata->base);
  93 
  94         return rc;
  95 }
  96 
  97 static int replicator_enable(struct coresight_device *csdev, int inport,
  98                              int outport)
  99 {
 100         int rc = 0;
 101         struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 102         unsigned long flags;
 103         bool first_enable = false;
 104 
 105         spin_lock_irqsave(&drvdata->spinlock, flags);
 106         if (atomic_read(&csdev->refcnt[outport]) == 0) {
 107                 if (drvdata->base)
 108                         rc = dynamic_replicator_enable(drvdata, inport,
 109                                                        outport);
 110                 if (!rc)
 111                         first_enable = true;
 112         }
 113         if (!rc)
 114                 atomic_inc(&csdev->refcnt[outport]);
 115         spin_unlock_irqrestore(&drvdata->spinlock, flags);
 116 
 117         if (first_enable)
 118                 dev_dbg(&csdev->dev, "REPLICATOR enabled\n");
 119         return rc;
 120 }
 121 
 122 static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
 123                                        int inport, int outport)
 124 {
 125         u32 reg;
 126 
 127         switch (outport) {
 128         case 0:
 129                 reg = REPLICATOR_IDFILTER0;
 130                 break;
 131         case 1:
 132                 reg = REPLICATOR_IDFILTER1;
 133                 break;
 134         default:
 135                 WARN_ON(1);
 136                 return;
 137         }
 138 
 139         CS_UNLOCK(drvdata->base);
 140 
 141         /* disable the flow of ATB data through port */
 142         writel_relaxed(0xff, drvdata->base + reg);
 143 
 144         if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) &&
 145             (readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff))
 146                 coresight_disclaim_device_unlocked(drvdata->base);
 147         CS_LOCK(drvdata->base);
 148 }
 149 
 150 static void replicator_disable(struct coresight_device *csdev, int inport,
 151                                int outport)
 152 {
 153         struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 154         unsigned long flags;
 155         bool last_disable = false;
 156 
 157         spin_lock_irqsave(&drvdata->spinlock, flags);
 158         if (atomic_dec_return(&csdev->refcnt[outport]) == 0) {
 159                 if (drvdata->base)
 160                         dynamic_replicator_disable(drvdata, inport, outport);
 161                 last_disable = true;
 162         }
 163         spin_unlock_irqrestore(&drvdata->spinlock, flags);
 164 
 165         if (last_disable)
 166                 dev_dbg(&csdev->dev, "REPLICATOR disabled\n");
 167 }
 168 
 169 static const struct coresight_ops_link replicator_link_ops = {
 170         .enable         = replicator_enable,
 171         .disable        = replicator_disable,
 172 };
 173 
 174 static const struct coresight_ops replicator_cs_ops = {
 175         .link_ops       = &replicator_link_ops,
 176 };
 177 
 178 #define coresight_replicator_reg(name, offset) \
 179         coresight_simple_reg32(struct replicator_drvdata, name, offset)
 180 
 181 coresight_replicator_reg(idfilter0, REPLICATOR_IDFILTER0);
 182 coresight_replicator_reg(idfilter1, REPLICATOR_IDFILTER1);
 183 
 184 static struct attribute *replicator_mgmt_attrs[] = {
 185         &dev_attr_idfilter0.attr,
 186         &dev_attr_idfilter1.attr,
 187         NULL,
 188 };
 189 
 190 static const struct attribute_group replicator_mgmt_group = {
 191         .attrs = replicator_mgmt_attrs,
 192         .name = "mgmt",
 193 };
 194 
 195 static const struct attribute_group *replicator_groups[] = {
 196         &replicator_mgmt_group,
 197         NULL,
 198 };
 199 
 200 static int replicator_probe(struct device *dev, struct resource *res)
 201 {
 202         int ret = 0;
 203         struct coresight_platform_data *pdata = NULL;
 204         struct replicator_drvdata *drvdata;
 205         struct coresight_desc desc = { 0 };
 206         void __iomem *base;
 207 
 208         if (is_of_node(dev_fwnode(dev)) &&
 209             of_device_is_compatible(dev->of_node, "arm,coresight-replicator"))
 210                 dev_warn_once(dev,
 211                               "Uses OBSOLETE CoreSight replicator binding\n");
 212 
 213         desc.name = coresight_alloc_device_name(&replicator_devs, dev);
 214         if (!desc.name)
 215                 return -ENOMEM;
 216 
 217         drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
 218         if (!drvdata)
 219                 return -ENOMEM;
 220 
 221         drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */
 222         if (!IS_ERR(drvdata->atclk)) {
 223                 ret = clk_prepare_enable(drvdata->atclk);
 224                 if (ret)
 225                         return ret;
 226         }
 227 
 228         /*
 229          * Map the device base for dynamic-replicator, which has been
 230          * validated by AMBA core
 231          */
 232         if (res) {
 233                 base = devm_ioremap_resource(dev, res);
 234                 if (IS_ERR(base)) {
 235                         ret = PTR_ERR(base);
 236                         goto out_disable_clk;
 237                 }
 238                 drvdata->base = base;
 239                 desc.groups = replicator_groups;
 240         }
 241 
 242         dev_set_drvdata(dev, drvdata);
 243 
 244         pdata = coresight_get_platform_data(dev);
 245         if (IS_ERR(pdata)) {
 246                 ret = PTR_ERR(pdata);
 247                 goto out_disable_clk;
 248         }
 249         dev->platform_data = pdata;
 250 
 251         desc.type = CORESIGHT_DEV_TYPE_LINK;
 252         desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
 253         desc.ops = &replicator_cs_ops;
 254         desc.pdata = dev->platform_data;
 255         desc.dev = dev;
 256 
 257         drvdata->csdev = coresight_register(&desc);
 258         if (IS_ERR(drvdata->csdev)) {
 259                 ret = PTR_ERR(drvdata->csdev);
 260                 goto out_disable_clk;
 261         }
 262 
 263         replicator_reset(drvdata);
 264         pm_runtime_put(dev);
 265 
 266 out_disable_clk:
 267         if (ret && !IS_ERR_OR_NULL(drvdata->atclk))
 268                 clk_disable_unprepare(drvdata->atclk);
 269         return ret;
 270 }
 271 
 272 static int static_replicator_probe(struct platform_device *pdev)
 273 {
 274         int ret;
 275 
 276         pm_runtime_get_noresume(&pdev->dev);
 277         pm_runtime_set_active(&pdev->dev);
 278         pm_runtime_enable(&pdev->dev);
 279 
 280         /* Static replicators do not have programming base */
 281         ret = replicator_probe(&pdev->dev, NULL);
 282 
 283         if (ret) {
 284                 pm_runtime_put_noidle(&pdev->dev);
 285                 pm_runtime_disable(&pdev->dev);
 286         }
 287 
 288         return ret;
 289 }
 290 
 291 #ifdef CONFIG_PM
 292 static int replicator_runtime_suspend(struct device *dev)
 293 {
 294         struct replicator_drvdata *drvdata = dev_get_drvdata(dev);
 295 
 296         if (drvdata && !IS_ERR(drvdata->atclk))
 297                 clk_disable_unprepare(drvdata->atclk);
 298 
 299         return 0;
 300 }
 301 
 302 static int replicator_runtime_resume(struct device *dev)
 303 {
 304         struct replicator_drvdata *drvdata = dev_get_drvdata(dev);
 305 
 306         if (drvdata && !IS_ERR(drvdata->atclk))
 307                 clk_prepare_enable(drvdata->atclk);
 308 
 309         return 0;
 310 }
 311 #endif
 312 
 313 static const struct dev_pm_ops replicator_dev_pm_ops = {
 314         SET_RUNTIME_PM_OPS(replicator_runtime_suspend,
 315                            replicator_runtime_resume, NULL)
 316 };
 317 
 318 static const struct of_device_id static_replicator_match[] = {
 319         {.compatible = "arm,coresight-replicator"},
 320         {.compatible = "arm,coresight-static-replicator"},
 321         {}
 322 };
 323 
 324 #ifdef CONFIG_ACPI
 325 static const struct acpi_device_id static_replicator_acpi_ids[] = {
 326         {"ARMHC985", 0}, /* ARM CoreSight Static Replicator */
 327         {}
 328 };
 329 #endif
 330 
 331 static struct platform_driver static_replicator_driver = {
 332         .probe          = static_replicator_probe,
 333         .driver         = {
 334                 .name   = "coresight-static-replicator",
 335                 .of_match_table = of_match_ptr(static_replicator_match),
 336                 .acpi_match_table = ACPI_PTR(static_replicator_acpi_ids),
 337                 .pm     = &replicator_dev_pm_ops,
 338                 .suppress_bind_attrs = true,
 339         },
 340 };
 341 builtin_platform_driver(static_replicator_driver);
 342 
 343 static int dynamic_replicator_probe(struct amba_device *adev,
 344                                     const struct amba_id *id)
 345 {
 346         return replicator_probe(&adev->dev, &adev->res);
 347 }
 348 
 349 static const struct amba_id dynamic_replicator_ids[] = {
 350         {
 351                 .id     = 0x000bb909,
 352                 .mask   = 0x000fffff,
 353         },
 354         {
 355                 /* Coresight SoC-600 */
 356                 .id     = 0x000bb9ec,
 357                 .mask   = 0x000fffff,
 358         },
 359         { 0, 0 },
 360 };
 361 
 362 static struct amba_driver dynamic_replicator_driver = {
 363         .drv = {
 364                 .name   = "coresight-dynamic-replicator",
 365                 .pm     = &replicator_dev_pm_ops,
 366                 .suppress_bind_attrs = true,
 367         },
 368         .probe          = dynamic_replicator_probe,
 369         .id_table       = dynamic_replicator_ids,
 370 };
 371 builtin_amba_driver(dynamic_replicator_driver);

/* [<][>][^][v][top][bottom][index][help] */