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_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode) { unsigned long flags; spin_lock_irqsave(&drvdata->spinlock, flags); if (drvdata->reading) 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 { if (mode == TMC_MODE_CIRCULAR_BUFFER) tmc_etb_disable_hw(drvdata); else tmc_etf_disable_hw(drvdata); } out: drvdata->enable = false; spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(drvdata->dev); dev_info(drvdata->dev, "TMC disabled\n"); }
static void tmc_disable_etr_sink(struct coresight_device *csdev) { long val; unsigned long flags; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); spin_lock_irqsave(&drvdata->spinlock, flags); if (drvdata->reading) { spin_unlock_irqrestore(&drvdata->spinlock, flags); return; } val = local_xchg(&drvdata->mode, CS_MODE_DISABLED); /* Disable the TMC only if it needs to */ if (val != CS_MODE_DISABLED) tmc_etr_disable_hw(drvdata); spin_unlock_irqrestore(&drvdata->spinlock, flags); dev_info(drvdata->dev, "TMC-ETR disabled\n"); }
int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) { int ret = 0; long val; unsigned long flags; /* config types are set a boot time and never change */ if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR)) return -EINVAL; spin_lock_irqsave(&drvdata->spinlock, flags); if (drvdata->reading) { ret = -EBUSY; goto out; } val = local_read(&drvdata->mode); /* Don't interfere if operated from Perf */ if (val == CS_MODE_PERF) { ret = -EINVAL; goto out; } /* If drvdata::buf is NULL the trace data has been read already */ if (drvdata->buf == NULL) { ret = -EINVAL; goto out; } /* Disable the TMC if need be */ if (val == CS_MODE_SYSFS) tmc_etr_disable_hw(drvdata); drvdata->reading = true; out: spin_unlock_irqrestore(&drvdata->spinlock, flags); return ret; }