diff options
Diffstat (limited to 'drivers/hwtracing')
20 files changed, 452 insertions, 141 deletions
diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index 8d55d6d79015..ef9cb3c164e1 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -70,13 +70,13 @@ config CORESIGHT_SOURCE_ETM4X for instruction level tracing. Depending on the implemented version data tracing may also be available. -config CORESIGHT_QCOM_REPLICATOR - bool "Qualcomm CoreSight Replicator driver" +config CORESIGHT_DYNAMIC_REPLICATOR + bool "CoreSight Programmable Replicator driver" depends on CORESIGHT_LINKS_AND_SINKS help - This enables support for Qualcomm CoreSight link driver. The - programmable ATB replicator sends the ATB trace stream from the - ETB/ETF to the TPIUi and ETR. + This enables support for dynamic CoreSight replicator link driver. + The programmable ATB replicator allows independent filtering of the + trace data based on the traceid. config CORESIGHT_STM bool "CoreSight System Trace Macrocell driver" diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 433d59025eb6..5bae90ce794d 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -14,6 +14,6 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o \ coresight-etm3x-sysfs.o obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \ coresight-etm4x-sysfs.o -obj-$(CONFIG_CORESIGHT_QCOM_REPLICATOR) += coresight-replicator-qcom.o +obj-$(CONFIG_CORESIGHT_DYNAMIC_REPLICATOR) += coresight-dynamic-replicator.o obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index 64a77e00eaa6..6ea62c62ff27 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -667,7 +667,7 @@ static int debug_remove(struct amba_device *adev) return 0; } -static struct amba_id debug_ids[] = { +static const struct amba_id debug_ids[] = { { /* Debug for Cortex-A53 */ .id = 0x000bbd03, .mask = 0x000fffff, diff --git a/drivers/hwtracing/coresight/coresight-replicator-qcom.c b/drivers/hwtracing/coresight/coresight-dynamic-replicator.c index 0a3d15f0b009..accc2056f7c6 100644 --- a/drivers/hwtracing/coresight/coresight-replicator-qcom.c +++ b/drivers/hwtracing/coresight/coresight-dynamic-replicator.c @@ -95,6 +95,28 @@ static const struct coresight_ops replicator_cs_ops = { .link_ops = &replicator_link_ops, }; +#define coresight_replicator_reg(name, offset) \ + coresight_simple_reg32(struct replicator_state, name, offset) + +coresight_replicator_reg(idfilter0, REPLICATOR_IDFILTER0); +coresight_replicator_reg(idfilter1, REPLICATOR_IDFILTER1); + +static struct attribute *replicator_mgmt_attrs[] = { + &dev_attr_idfilter0.attr, + &dev_attr_idfilter1.attr, + NULL, +}; + +static const struct attribute_group replicator_mgmt_group = { + .attrs = replicator_mgmt_attrs, + .name = "mgmt", +}; + +static const struct attribute_group *replicator_groups[] = { + &replicator_mgmt_group, + NULL, +}; + static int replicator_probe(struct amba_device *adev, const struct amba_id *id) { int ret; @@ -139,11 +161,11 @@ static int replicator_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &replicator_cs_ops; desc.pdata = adev->dev.platform_data; desc.dev = &adev->dev; + desc.groups = replicator_groups; drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) return PTR_ERR(drvdata->csdev); - dev_info(dev, "%s initialized\n", (char *)id->data); return 0; } @@ -175,18 +197,22 @@ static const struct dev_pm_ops replicator_dev_pm_ops = { NULL) }; -static struct amba_id replicator_ids[] = { +static const struct amba_id replicator_ids[] = { { .id = 0x0003b909, .mask = 0x0003ffff, - .data = "REPLICATOR 1.0", + }, + { + /* Coresight SoC-600 */ + .id = 0x000bb9ec, + .mask = 0x000fffff, }, { 0, 0 }, }; static struct amba_driver replicator_driver = { .drv = { - .name = "coresight-replicator-qcom", + .name = "coresight-dynamic-replicator", .pm = &replicator_dev_pm_ops, .suppress_bind_attrs = true, }, diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index d5b96423e1a5..56ecd7aff5eb 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -200,8 +200,10 @@ static void etb_disable_hw(struct etb_drvdata *drvdata) static void etb_dump_hw(struct etb_drvdata *drvdata) { + bool lost = false; int i; u8 *buf_ptr; + const u32 *barrier; u32 read_data, depth; u32 read_ptr, write_ptr; u32 frame_off, frame_endoff; @@ -223,20 +225,26 @@ static void etb_dump_hw(struct etb_drvdata *drvdata) } if ((readl_relaxed(drvdata->base + ETB_STATUS_REG) - & ETB_STATUS_RAM_FULL) == 0) + & ETB_STATUS_RAM_FULL) == 0) { writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER); - else + } else { writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER); + lost = true; + } depth = drvdata->buffer_depth; buf_ptr = drvdata->buf; + barrier = barrier_pkt; for (i = 0; i < depth; i++) { read_data = readl_relaxed(drvdata->base + ETB_RAM_READ_DATA_REG); - *buf_ptr++ = read_data >> 0; - *buf_ptr++ = read_data >> 8; - *buf_ptr++ = read_data >> 16; - *buf_ptr++ = read_data >> 24; + if (lost && *barrier) { + read_data = *barrier; + barrier++; + } + + *(u32 *)buf_ptr = read_data; + buf_ptr += 4; } if (frame_off) { @@ -353,8 +361,10 @@ static void etb_update_buffer(struct coresight_device *csdev, struct perf_output_handle *handle, void *sink_config) { + bool lost = false; int i, cur; u8 *buf_ptr; + const u32 *barrier; u32 read_ptr, write_ptr, capacity; u32 status, read_data, to_read; unsigned long offset; @@ -366,8 +376,8 @@ static void etb_update_buffer(struct coresight_device *csdev, capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS; - CS_UNLOCK(drvdata->base); etb_disable_hw(drvdata); + CS_UNLOCK(drvdata->base); /* unit is in words, not bytes */ read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER); @@ -384,7 +394,7 @@ static void etb_update_buffer(struct coresight_device *csdev, (unsigned long)write_ptr); write_ptr &= ~(ETB_FRAME_SIZE_WORDS - 1); - perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); + lost = true; } /* @@ -395,7 +405,7 @@ static void etb_update_buffer(struct coresight_device *csdev, */ status = readl_relaxed(drvdata->base + ETB_STATUS_REG); if (status & ETB_STATUS_RAM_FULL) { - perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); + lost = true; to_read = capacity; read_ptr = write_ptr; } else { @@ -428,22 +438,30 @@ static void etb_update_buffer(struct coresight_device *csdev, if (read_ptr > (drvdata->buffer_depth - 1)) read_ptr -= drvdata->buffer_depth; /* let the decoder know we've skipped ahead */ - perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); + lost = true; } + if (lost) + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); + /* finally tell HW where we want to start reading from */ writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER); cur = buf->cur; offset = buf->offset; + barrier = barrier_pkt; + for (i = 0; i < to_read; i += 4) { buf_ptr = buf->data_pages[cur] + offset; read_data = readl_relaxed(drvdata->base + ETB_RAM_READ_DATA_REG); - *buf_ptr++ = read_data >> 0; - *buf_ptr++ = read_data >> 8; - *buf_ptr++ = read_data >> 16; - *buf_ptr++ = read_data >> 24; + if (lost && *barrier) { + read_data = *barrier; + barrier++; + } + + *(u32 *)buf_ptr = read_data; + buf_ptr += 4; offset += 4; if (offset >= PAGE_SIZE) { @@ -557,17 +575,17 @@ static const struct file_operations etb_fops = { .llseek = no_llseek, }; -#define coresight_etb10_simple_func(name, offset) \ - coresight_simple_func(struct etb_drvdata, NULL, name, offset) +#define coresight_etb10_reg(name, offset) \ + coresight_simple_reg32(struct etb_drvdata, name, offset) -coresight_etb10_simple_func(rdp, ETB_RAM_DEPTH_REG); -coresight_etb10_simple_func(sts, ETB_STATUS_REG); -coresight_etb10_simple_func(rrp, ETB_RAM_READ_POINTER); -coresight_etb10_simple_func(rwp, ETB_RAM_WRITE_POINTER); -coresight_etb10_simple_func(trg, ETB_TRG); -coresight_etb10_simple_func(ctl, ETB_CTL_REG); -coresight_etb10_simple_func(ffsr, ETB_FFSR); -coresight_etb10_simple_func(ffcr, ETB_FFCR); +coresight_etb10_reg(rdp, ETB_RAM_DEPTH_REG); +coresight_etb10_reg(sts, ETB_STATUS_REG); +coresight_etb10_reg(rrp, ETB_RAM_READ_POINTER); +coresight_etb10_reg(rwp, ETB_RAM_WRITE_POINTER); +coresight_etb10_reg(trg, ETB_TRG); +coresight_etb10_reg(ctl, ETB_CTL_REG); +coresight_etb10_reg(ffsr, ETB_FFSR); +coresight_etb10_reg(ffcr, ETB_FFCR); static struct attribute *coresight_etb_mgmt_attrs[] = { &dev_attr_rdp.attr, @@ -728,7 +746,7 @@ static const struct dev_pm_ops etb_dev_pm_ops = { SET_RUNTIME_PM_OPS(etb_runtime_suspend, etb_runtime_resume, NULL) }; -static struct amba_id etb_ids[] = { +static const struct amba_id etb_ids[] = { { .id = 0x0003b907, .mask = 0x0003ffff, diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index 8f546f59a3fd..8a0ad77574e7 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -53,14 +53,16 @@ static DEFINE_PER_CPU(struct coresight_device *, csdev_src); /* ETMv3.5/PTM's ETMCR is 'config' */ PMU_FORMAT_ATTR(cycacc, "config:" __stringify(ETM_OPT_CYCACC)); PMU_FORMAT_ATTR(timestamp, "config:" __stringify(ETM_OPT_TS)); +PMU_FORMAT_ATTR(retstack, "config:" __stringify(ETM_OPT_RETSTK)); static struct attribute *etm_config_formats_attr[] = { &format_attr_cycacc.attr, &format_attr_timestamp.attr, + &format_attr_retstack.attr, NULL, }; -static struct attribute_group etm_pmu_format_group = { +static const struct attribute_group etm_pmu_format_group = { .name = "format", .attrs = etm_config_formats_attr, }; diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h index ad063d7444e1..70b0a248c321 100644 --- a/drivers/hwtracing/coresight/coresight-etm.h +++ b/drivers/hwtracing/coresight/coresight-etm.h @@ -106,6 +106,7 @@ #define ETMTECR1_START_STOP BIT(25) /* ETMCCER - 0x1E8 */ #define ETMCCER_TIMESTAMP BIT(22) +#define ETMCCER_RETSTACK BIT(23) #define ETM_MODE_EXCLUDE BIT(0) #define ETM_MODE_CYCACC BIT(1) diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c index ca98ad13bb8c..6e547ec6fead 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c @@ -1232,19 +1232,19 @@ static struct attribute *coresight_etm_attrs[] = { NULL, }; -#define coresight_etm3x_simple_func(name, offset) \ - coresight_simple_func(struct etm_drvdata, NULL, name, offset) - -coresight_etm3x_simple_func(etmccr, ETMCCR); -coresight_etm3x_simple_func(etmccer, ETMCCER); -coresight_etm3x_simple_func(etmscr, ETMSCR); -coresight_etm3x_simple_func(etmidr, ETMIDR); -coresight_etm3x_simple_func(etmcr, ETMCR); -coresight_etm3x_simple_func(etmtraceidr, ETMTRACEIDR); -coresight_etm3x_simple_func(etmteevr, ETMTEEVR); -coresight_etm3x_simple_func(etmtssvr, ETMTSSCR); -coresight_etm3x_simple_func(etmtecr1, ETMTECR1); -coresight_etm3x_simple_func(etmtecr2, ETMTECR2); +#define coresight_etm3x_reg(name, offset) \ + coresight_simple_reg32(struct etm_drvdata, name, offset) + +coresight_etm3x_reg(etmccr, ETMCCR); +coresight_etm3x_reg(etmccer, ETMCCER); +coresight_etm3x_reg(etmscr, ETMSCR); +coresight_etm3x_reg(etmidr, ETMIDR); +coresight_etm3x_reg(etmcr, ETMCR); +coresight_etm3x_reg(etmtraceidr, ETMTRACEIDR); +coresight_etm3x_reg(etmteevr, ETMTEEVR); +coresight_etm3x_reg(etmtssvr, ETMTSSCR); +coresight_etm3x_reg(etmtecr1, ETMTECR1); +coresight_etm3x_reg(etmtecr2, ETMTECR2); static struct attribute *coresight_etm_mgmt_attrs[] = { &dev_attr_etmccr.attr, diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index 93ee8fc539be..e5b1ec57dbde 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -243,6 +243,8 @@ void etm_set_default(struct etm_config *config) } config->ctxid_mask = 0x0; + /* Setting default to 1024 as per TRM recommendation */ + config->sync_freq = 0x400; } void etm_config_trace_mode(struct etm_config *config) @@ -308,7 +310,9 @@ void etm_config_trace_mode(struct etm_config *config) config->addr_type[1] = ETM_ADDR_TYPE_RANGE; } -#define ETM3X_SUPPORTED_OPTIONS (ETMCR_CYC_ACC | ETMCR_TIMESTAMP_EN) +#define ETM3X_SUPPORTED_OPTIONS (ETMCR_CYC_ACC | \ + ETMCR_TIMESTAMP_EN | \ + ETMCR_RETURN_STACK) static int etm_parse_event_config(struct etm_drvdata *drvdata, struct perf_event *event) @@ -339,14 +343,24 @@ static int etm_parse_event_config(struct etm_drvdata *drvdata, etm_config_trace_mode(config); /* - * At this time only cycle accurate and timestamp options are - * available. + * At this time only cycle accurate, return stack and timestamp + * options are available. */ if (attr->config & ~ETM3X_SUPPORTED_OPTIONS) return -EINVAL; config->ctrl = attr->config; + /* + * Possible to have cores with PTM (supports ret stack) and ETM + * (never has ret stack) on the same SoC. So if we have a request + * for return stack that can't be honoured on this core then + * clear the bit - trace will still continue normally + */ + if ((config->ctrl & ETMCR_RETURN_STACK) && + !(drvdata->etmccer & ETMCCER_RETSTACK)) + config->ctrl &= ~ETMCR_RETURN_STACK; + return 0; } @@ -885,7 +899,7 @@ static const struct dev_pm_ops etm_dev_pm_ops = { SET_RUNTIME_PM_OPS(etm_runtime_suspend, etm_runtime_resume, NULL) }; -static struct amba_id etm_ids[] = { +static const struct amba_id etm_ids[] = { { /* ETM 3.3 */ .id = 0x0003b921, .mask = 0x0003ffff, diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index b9b1e9c8f4c4..4e6eab53e34e 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -2066,23 +2066,23 @@ static u32 etmv4_cross_read(const struct device *dev, u32 offset) return reg.data; } -#define coresight_etm4x_simple_func(name, offset) \ - coresight_simple_func(struct etmv4_drvdata, NULL, name, offset) +#define coresight_etm4x_reg(name, offset) \ + coresight_simple_reg32(struct etmv4_drvdata, name, offset) #define coresight_etm4x_cross_read(name, offset) \ coresight_simple_func(struct etmv4_drvdata, etmv4_cross_read, \ name, offset) -coresight_etm4x_simple_func(trcpdcr, TRCPDCR); -coresight_etm4x_simple_func(trcpdsr, TRCPDSR); -coresight_etm4x_simple_func(trclsr, TRCLSR); -coresight_etm4x_simple_func(trcauthstatus, TRCAUTHSTATUS); -coresight_etm4x_simple_func(trcdevid, TRCDEVID); -coresight_etm4x_simple_func(trcdevtype, TRCDEVTYPE); -coresight_etm4x_simple_func(trcpidr0, TRCPIDR0); -coresight_etm4x_simple_func(trcpidr1, TRCPIDR1); -coresight_etm4x_simple_func(trcpidr2, TRCPIDR2); -coresight_etm4x_simple_func(trcpidr3, TRCPIDR3); +coresight_etm4x_reg(trcpdcr, TRCPDCR); +coresight_etm4x_reg(trcpdsr, TRCPDSR); +coresight_etm4x_reg(trclsr, TRCLSR); +coresight_etm4x_reg(trcauthstatus, TRCAUTHSTATUS); +coresight_etm4x_reg(trcdevid, TRCDEVID); +coresight_etm4x_reg(trcdevtype, TRCDEVTYPE); +coresight_etm4x_reg(trcpidr0, TRCPIDR0); +coresight_etm4x_reg(trcpidr1, TRCPIDR1); +coresight_etm4x_reg(trcpidr2, TRCPIDR2); +coresight_etm4x_reg(trcpidr3, TRCPIDR3); coresight_etm4x_cross_read(trcoslsr, TRCOSLSR); coresight_etm4x_cross_read(trcconfig, TRCCONFIGR); coresight_etm4x_cross_read(trctraceid, TRCTRACEIDR); diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 532adc9dd32a..cf364a514c12 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -224,6 +224,10 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata, if (attr->config & BIT(ETM_OPT_TS)) /* bit[11], Global timestamp tracing bit */ config->cfg |= BIT(11); + /* return stack - enable if selected and supported */ + if ((attr->config & BIT(ETM_OPT_RETSTK)) && drvdata->retstack) + /* bit[12], Return stack enable bit */ + config->cfg |= BIT(12); out: return ret; @@ -1048,7 +1052,7 @@ err_arch_supported: return ret; } -static struct amba_id etm4_ids[] = { +static const struct amba_id etm4_ids[] = { { /* ETM 4.0 - Cortex-A53 */ .id = 0x000bb95d, .mask = 0x000fffff, diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 860fe6ef5632..77642e0e955b 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -246,11 +246,16 @@ static const struct dev_pm_ops funnel_dev_pm_ops = { SET_RUNTIME_PM_OPS(funnel_runtime_suspend, funnel_runtime_resume, NULL) }; -static struct amba_id funnel_ids[] = { +static const struct amba_id funnel_ids[] = { { .id = 0x0003b908, .mask = 0x0003ffff, }, + { + /* Coresight SoC-600 */ + .id = 0x000bb9eb, + .mask = 0x000fffff, + }, { 0, 0}, }; diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 5f662d82052c..f1d0e21d8cab 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -39,23 +39,33 @@ #define ETM_MODE_EXCL_USER BIT(31) typedef u32 (*coresight_read_fn)(const struct device *, u32 offset); -#define coresight_simple_func(type, func, name, offset) \ +#define __coresight_simple_func(type, func, name, lo_off, hi_off) \ static ssize_t name##_show(struct device *_dev, \ struct device_attribute *attr, char *buf) \ { \ type *drvdata = dev_get_drvdata(_dev->parent); \ coresight_read_fn fn = func; \ - u32 val; \ + u64 val; \ pm_runtime_get_sync(_dev->parent); \ if (fn) \ - val = fn(_dev->parent, offset); \ + val = (u64)fn(_dev->parent, lo_off); \ else \ - val = readl_relaxed(drvdata->base + offset); \ + val = coresight_read_reg_pair(drvdata->base, \ + lo_off, hi_off); \ pm_runtime_put_sync(_dev->parent); \ - return scnprintf(buf, PAGE_SIZE, "0x%x\n", val); \ + return scnprintf(buf, PAGE_SIZE, "0x%llx\n", val); \ } \ static DEVICE_ATTR_RO(name) +#define coresight_simple_func(type, func, name, offset) \ + __coresight_simple_func(type, func, name, offset, -1) +#define coresight_simple_reg32(type, name, offset) \ + __coresight_simple_func(type, NULL, name, offset, -1) +#define coresight_simple_reg64(type, name, lo_off, hi_off) \ + __coresight_simple_func(type, NULL, name, lo_off, hi_off) + +extern const u32 barrier_pkt[5]; + enum etm_addr_type { ETM_ADDR_TYPE_NONE, ETM_ADDR_TYPE_SINGLE, @@ -106,6 +116,25 @@ static inline void CS_UNLOCK(void __iomem *addr) } while (0); } +static inline u64 +coresight_read_reg_pair(void __iomem *addr, s32 lo_offset, s32 hi_offset) +{ + u64 val; + + val = readl_relaxed(addr + lo_offset); + val |= (hi_offset < 0) ? 0 : + (u64)readl_relaxed(addr + hi_offset) << 32; + return val; +} + +static inline void coresight_write_reg_pair(void __iomem *addr, u64 val, + s32 lo_offset, s32 hi_offset) +{ + writel_relaxed((u32)val, addr + lo_offset); + if (hi_offset >= 0) + writel_relaxed((u32)(val >> 32), addr + hi_offset); +} + void coresight_disable_path(struct list_head *path); int coresight_enable_path(struct list_head *path, u32 mode); struct coresight_device *coresight_get_sink(struct list_head *path); diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 93fc26f01bab..92a780a6df1d 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -276,7 +276,7 @@ static void stm_disable(struct coresight_device *csdev, spin_unlock(&drvdata->spinlock); /* Wait until the engine has completely stopped */ - coresight_timeout(drvdata, STMTCSR, STMTCSR_BUSY_BIT, 0); + coresight_timeout(drvdata->base, STMTCSR, STMTCSR_BUSY_BIT, 0); pm_runtime_put(drvdata->dev); @@ -307,7 +307,8 @@ static inline bool stm_addr_unaligned(const void *addr, u8 write_bytes) return ((unsigned long)addr & (write_bytes - 1)); } -static void stm_send(void *addr, const void *data, u32 size, u8 write_bytes) +static void stm_send(void __iomem *addr, const void *data, + u32 size, u8 write_bytes) { u8 paload[8]; @@ -414,7 +415,7 @@ static ssize_t notrace stm_generic_packet(struct stm_data *stm_data, unsigned int size, const unsigned char *payload) { - unsigned long ch_addr; + void __iomem *ch_addr; struct stm_drvdata *drvdata = container_of(stm_data, struct stm_drvdata, stm); @@ -424,7 +425,7 @@ static ssize_t notrace stm_generic_packet(struct stm_data *stm_data, if (channel >= drvdata->numsp) return -EINVAL; - ch_addr = (unsigned long)stm_channel_addr(drvdata, channel); + ch_addr = stm_channel_addr(drvdata, channel); flags = (flags == STP_PACKET_TIMESTAMPED) ? STM_FLAG_TIMESTAMPED : 0; flags |= test_bit(channel, drvdata->chs.guaranteed) ? @@ -437,20 +438,20 @@ static ssize_t notrace stm_generic_packet(struct stm_data *stm_data, switch (packet) { case STP_PACKET_FLAG: - ch_addr |= stm_channel_off(STM_PKT_TYPE_FLAG, flags); + ch_addr += stm_channel_off(STM_PKT_TYPE_FLAG, flags); /* * The generic STM core sets a size of '0' on flag packets. * As such send a flag packet of size '1' and tell the * core we did so. */ - stm_send((void *)ch_addr, payload, 1, drvdata->write_bytes); + stm_send(ch_addr, payload, 1, drvdata->write_bytes); size = 1; break; case STP_PACKET_DATA: - ch_addr |= stm_channel_off(STM_PKT_TYPE_DATA, flags); - stm_send((void *)ch_addr, payload, size, + ch_addr += stm_channel_off(STM_PKT_TYPE_DATA, flags); + stm_send(ch_addr, payload, size, drvdata->write_bytes); break; @@ -635,21 +636,21 @@ static ssize_t traceid_store(struct device *dev, } static DEVICE_ATTR_RW(traceid); -#define coresight_stm_simple_func(name, offset) \ - coresight_simple_func(struct stm_drvdata, NULL, name, offset) - -coresight_stm_simple_func(tcsr, STMTCSR); -coresight_stm_simple_func(tsfreqr, STMTSFREQR); -coresight_stm_simple_func(syncr, STMSYNCR); -coresight_stm_simple_func(sper, STMSPER); -coresight_stm_simple_func(spter, STMSPTER); -coresight_stm_simple_func(privmaskr, STMPRIVMASKR); -coresight_stm_simple_func(spscr, STMSPSCR); -coresight_stm_simple_func(spmscr, STMSPMSCR); -coresight_stm_simple_func(spfeat1r, STMSPFEAT1R); -coresight_stm_simple_func(spfeat2r, STMSPFEAT2R); -coresight_stm_simple_func(spfeat3r, STMSPFEAT3R); -coresight_stm_simple_func(devid, CORESIGHT_DEVID); +#define coresight_stm_reg(name, offset) \ + coresight_simple_reg32(struct stm_drvdata, name, offset) + +coresight_stm_reg(tcsr, STMTCSR); +coresight_stm_reg(tsfreqr, STMTSFREQR); +coresight_stm_reg(syncr, STMSYNCR); +coresight_stm_reg(sper, STMSPER); +coresight_stm_reg(spter, STMSPTER); +coresight_stm_reg(privmaskr, STMPRIVMASKR); +coresight_stm_reg(spscr, STMSPSCR); +coresight_stm_reg(spmscr, STMSPMSCR); +coresight_stm_reg(spfeat1r, STMSPFEAT1R); +coresight_stm_reg(spfeat2r, STMSPFEAT2R); +coresight_stm_reg(spfeat3r, STMSPFEAT3R); +coresight_stm_reg(devid, CORESIGHT_DEVID); static struct attribute *coresight_stm_attrs[] = { &dev_attr_hwevent_enable.attr, @@ -914,7 +915,7 @@ static const struct dev_pm_ops stm_dev_pm_ops = { SET_RUNTIME_PM_OPS(stm_runtime_suspend, stm_runtime_resume, NULL) }; -static struct amba_id stm_ids[] = { +static const struct amba_id stm_ids[] = { { .id = 0x0003b962, .mask = 0x0003ffff, diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index e3b9fb82eb8d..e2513b786242 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -43,17 +43,34 @@ static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata) static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata) { + bool lost = false; char *bufp; - u32 read_data; + const u32 *barrier; + u32 read_data, status; int i; + /* + * Get a hold of the status register and see if a wrap around + * has occurred. + */ + status = readl_relaxed(drvdata->base + TMC_STS); + if (status & TMC_STS_FULL) + lost = true; + bufp = drvdata->buf; drvdata->len = 0; + barrier = barrier_pkt; while (1) { for (i = 0; i < drvdata->memwidth; i++) { read_data = readl_relaxed(drvdata->base + TMC_RRD); if (read_data == 0xFFFFFFFF) return; + + if (lost && *barrier) { + read_data = *barrier; + barrier++; + } + memcpy(bufp, &read_data, 4); bufp += 4; drvdata->len += 4; @@ -369,9 +386,11 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev, struct perf_output_handle *handle, void *sink_config) { + bool lost = false; int i, cur; + const u32 *barrier; u32 *buf_ptr; - u32 read_ptr, write_ptr; + u64 read_ptr, write_ptr; u32 status, to_read; unsigned long offset; struct cs_buffers *buf = sink_config; @@ -388,8 +407,8 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev, tmc_flush_and_stop(drvdata); - read_ptr = readl_relaxed(drvdata->base + TMC_RRP); - write_ptr = readl_relaxed(drvdata->base + TMC_RWP); + read_ptr = tmc_read_rrp(drvdata); + write_ptr = tmc_read_rwp(drvdata); /* * Get a hold of the status register and see if a wrap around @@ -397,7 +416,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev, */ status = readl_relaxed(drvdata->base + TMC_STS); if (status & TMC_STS_FULL) { - perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); + lost = true; to_read = drvdata->size; } else { to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size); @@ -441,18 +460,27 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev, if (read_ptr > (drvdata->size - 1)) read_ptr -= drvdata->size; /* Tell the HW */ - writel_relaxed(read_ptr, drvdata->base + TMC_RRP); - perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); + tmc_write_rrp(drvdata, read_ptr); + lost = true; } + if (lost) + perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); + cur = buf->cur; offset = buf->offset; + barrier = barrier_pkt; /* for every byte to read */ for (i = 0; i < to_read; i += 4) { buf_ptr = buf->data_pages[cur] + offset; *buf_ptr = readl_relaxed(drvdata->base + TMC_RRD); + if (lost && *barrier) { + *buf_ptr = *barrier; + barrier++; + } + offset += 4; if (offset >= PAGE_SIZE) { offset = 0; diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 5d312699b3b9..68fbc8f7450e 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -22,7 +22,7 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) { - u32 axictl; + u32 axictl, sts; /* Zero out the memory to help with debug */ memset(drvdata->vaddr, 0, drvdata->size); @@ -36,17 +36,29 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE); axictl = readl_relaxed(drvdata->base + TMC_AXICTL); - axictl |= TMC_AXICTL_WR_BURST_16; - 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; + axictl &= ~TMC_AXICTL_CLEAR_MASK; + axictl |= (TMC_AXICTL_PROT_CTL_B1 | TMC_AXICTL_WR_BURST_16); + axictl |= TMC_AXICTL_AXCACHE_OS; + + if (tmc_etr_has_cap(drvdata, TMC_ETR_AXI_ARCACHE)) { + axictl &= ~TMC_AXICTL_ARCACHE_MASK; + axictl |= TMC_AXICTL_ARCACHE_OS; + } + writel_relaxed(axictl, drvdata->base + TMC_AXICTL); + tmc_write_dba(drvdata, drvdata->paddr); + /* + * If the TMC pointers must be programmed before the session, + * we have to set it properly (i.e, RRP/RWP to base address and + * STS to "not full"). + */ + if (tmc_etr_has_cap(drvdata, TMC_ETR_SAVE_RESTORE)) { + tmc_write_rrp(drvdata, drvdata->paddr); + tmc_write_rwp(drvdata, drvdata->paddr); + sts = readl_relaxed(drvdata->base + TMC_STS) & ~TMC_STS_FULL; + writel_relaxed(sts, drvdata->base + TMC_STS); + } - 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, @@ -59,9 +71,12 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata) { - u32 rwp, val; + const u32 *barrier; + u32 val; + u32 *temp; + u64 rwp; - rwp = readl_relaxed(drvdata->base + TMC_RWP); + rwp = tmc_read_rwp(drvdata); val = readl_relaxed(drvdata->base + TMC_STS); /* @@ -71,6 +86,16 @@ static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata) if (val & TMC_STS_FULL) { drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr; drvdata->len = drvdata->size; + + barrier = barrier_pkt; + temp = (u32 *)drvdata->buf; + + while (*barrier) { + *temp = *barrier; + temp++; + barrier++; + } + } else { drvdata->buf = drvdata->vaddr; drvdata->len = rwp - drvdata->paddr; diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 864488793f09..2ff4a66a3caa 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -217,20 +217,24 @@ static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid) return memwidth; } -#define coresight_tmc_simple_func(name, offset) \ - coresight_simple_func(struct tmc_drvdata, NULL, 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); +#define coresight_tmc_reg(name, offset) \ + coresight_simple_reg32(struct tmc_drvdata, name, offset) +#define coresight_tmc_reg64(name, lo_off, hi_off) \ + coresight_simple_reg64(struct tmc_drvdata, name, lo_off, hi_off) + +coresight_tmc_reg(rsz, TMC_RSZ); +coresight_tmc_reg(sts, TMC_STS); +coresight_tmc_reg(trg, TMC_TRG); +coresight_tmc_reg(ctl, TMC_CTL); +coresight_tmc_reg(ffsr, TMC_FFSR); +coresight_tmc_reg(ffcr, TMC_FFCR); +coresight_tmc_reg(mode, TMC_MODE); +coresight_tmc_reg(pscr, TMC_PSCR); +coresight_tmc_reg(axictl, TMC_AXICTL); +coresight_tmc_reg(devid, CORESIGHT_DEVID); +coresight_tmc_reg64(rrp, TMC_RRP, TMC_RRPHI); +coresight_tmc_reg64(rwp, TMC_RWP, TMC_RWPHI); +coresight_tmc_reg64(dba, TMC_DBALO, TMC_DBAHI); static struct attribute *coresight_tmc_mgmt_attrs[] = { &dev_attr_rsz.attr, @@ -244,6 +248,8 @@ static struct attribute *coresight_tmc_mgmt_attrs[] = { &dev_attr_mode.attr, &dev_attr_pscr.attr, &dev_attr_devid.attr, + &dev_attr_dba.attr, + &dev_attr_axictl.attr, NULL, }; @@ -293,6 +299,42 @@ const struct attribute_group *coresight_tmc_groups[] = { NULL, }; +/* Detect and initialise the capabilities of a TMC ETR */ +static int tmc_etr_setup_caps(struct tmc_drvdata *drvdata, + u32 devid, void *dev_caps) +{ + u32 dma_mask = 0; + + /* Set the unadvertised capabilities */ + tmc_etr_init_caps(drvdata, (u32)(unsigned long)dev_caps); + + if (!(devid & TMC_DEVID_NOSCAT)) + tmc_etr_set_cap(drvdata, TMC_ETR_SG); + + /* Check if the AXI address width is available */ + if (devid & TMC_DEVID_AXIAW_VALID) + dma_mask = ((devid >> TMC_DEVID_AXIAW_SHIFT) & + TMC_DEVID_AXIAW_MASK); + + /* + * Unless specified in the device configuration, ETR uses a 40-bit + * AXI master in place of the embedded SRAM of ETB/ETF. + */ + switch (dma_mask) { + case 32: + case 40: + case 44: + case 48: + case 52: + dev_info(drvdata->dev, "Detected dma mask %dbits\n", dma_mask); + break; + default: + dma_mask = 40; + } + + return dma_set_mask_and_coherent(drvdata->dev, DMA_BIT_MASK(dma_mask)); +} + static int tmc_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; @@ -354,25 +396,29 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) desc.dev = dev; desc.groups = coresight_tmc_groups; - if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) { + switch (drvdata->config_type) { + case TMC_CONFIG_TYPE_ETB: desc.type = CORESIGHT_DEV_TYPE_SINK; desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; desc.ops = &tmc_etb_cs_ops; - } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { + break; + case TMC_CONFIG_TYPE_ETR: desc.type = CORESIGHT_DEV_TYPE_SINK; desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; desc.ops = &tmc_etr_cs_ops; - /* - * ETR configuration uses a 40-bit AXI master in place of - * the embedded SRAM of ETB/ETF. - */ - ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); + ret = tmc_etr_setup_caps(drvdata, devid, id->data); if (ret) goto out; - } else { + break; + case TMC_CONFIG_TYPE_ETF: desc.type = CORESIGHT_DEV_TYPE_LINKSINK; desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO; desc.ops = &tmc_etf_cs_ops; + break; + default: + pr_err("%s: Unsupported TMC config\n", pdata->name); + ret = -EINVAL; + goto out; } drvdata->csdev = coresight_register(&desc); @@ -391,11 +437,27 @@ out: return ret; } -static struct amba_id tmc_ids[] = { +static const struct amba_id tmc_ids[] = { { .id = 0x0003b961, .mask = 0x0003ffff, }, + { + /* Coresight SoC 600 TMC-ETR/ETS */ + .id = 0x000bb9e8, + .mask = 0x000fffff, + .data = (void *)(unsigned long)CORESIGHT_SOC_600_ETR_CAPS, + }, + { + /* Coresight SoC 600 TMC-ETB */ + .id = 0x000bb9e9, + .mask = 0x000fffff, + }, + { + /* Coresight SoC 600 TMC-ETF */ + .id = 0x000bb9ea, + .mask = 0x000fffff, + }, { 0, 0}, }; diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 51c01851533e..8df7a813f537 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -54,11 +54,32 @@ #define TMC_STS_TMCREADY_BIT 2 #define TMC_STS_FULL BIT(0) #define TMC_STS_TRIGGERED BIT(1) -/* TMC_AXICTL - 0x110 */ +/* + * TMC_AXICTL - 0x110 + * + * TMC AXICTL format for SoC-400 + * Bits [0-1] : ProtCtrlBit0-1 + * Bits [2-5] : CacheCtrlBits 0-3 (AXCACHE) + * Bit 6 : Reserved + * Bit 7 : ScatterGatherMode + * Bits [8-11] : WrBurstLen + * Bits [12-31] : Reserved. + * TMC AXICTL format for SoC-600, as above except: + * Bits [2-5] : AXI WCACHE + * Bits [16-19] : AXI RCACHE + * Bits [20-31] : Reserved + */ +#define TMC_AXICTL_CLEAR_MASK 0xfbf +#define TMC_AXICTL_ARCACHE_MASK (0xf << 16) + #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_16 0xF00 +/* Write-back Read and Write-allocate */ +#define TMC_AXICTL_AXCACHE_OS (0xf << 2) +#define TMC_AXICTL_ARCACHE_OS (0xf << 16) + /* TMC_FFCR - 0x304 */ #define TMC_FFCR_FLUSHMAN_BIT 6 #define TMC_FFCR_EN_FMT BIT(0) @@ -69,6 +90,12 @@ #define TMC_FFCR_STOP_ON_FLUSH BIT(12) +#define TMC_DEVID_NOSCAT BIT(24) + +#define TMC_DEVID_AXIAW_VALID BIT(16) +#define TMC_DEVID_AXIAW_SHIFT 17 +#define TMC_DEVID_AXIAW_MASK 0x7f + enum tmc_config_type { TMC_CONFIG_TYPE_ETB, TMC_CONFIG_TYPE_ETR, @@ -88,6 +115,24 @@ enum tmc_mem_intf_width { TMC_MEM_INTF_WIDTH_256BITS = 8, }; +/* TMC ETR Capability bit definitions */ +#define TMC_ETR_SG (0x1U << 0) +/* ETR has separate read/write cache encodings */ +#define TMC_ETR_AXI_ARCACHE (0x1U << 1) +/* + * TMC_ETR_SAVE_RESTORE - Values of RRP/RWP/STS.Full are + * retained when TMC leaves Disabled state, allowing us to continue + * the tracing from a point where we stopped. This also implies that + * the RRP/RWP/STS.Full should always be programmed to the correct + * value. Unfortunately this is not advertised by the hardware, + * so we have to rely on PID of the IP to detect the functionality. + */ +#define TMC_ETR_SAVE_RESTORE (0x1U << 2) + +/* Coresight SoC-600 TMC-ETR unadvertised capabilities */ +#define CORESIGHT_SOC_600_ETR_CAPS \ + (TMC_ETR_SAVE_RESTORE | TMC_ETR_AXI_ARCACHE) + /** * struct tmc_drvdata - specifics associated to an TMC component * @base: memory mapped base address for this component. @@ -104,6 +149,8 @@ enum tmc_mem_intf_width { * @config_type: TMC variant, must be of type @tmc_config_type. * @memwidth: width of the memory interface databus, in bytes. * @trigger_cntr: amount of words to store after a trigger. + * @etr_caps: Bitmask of capabilities of the TMC ETR, inferred from the + * device configuration register (DEVID) */ struct tmc_drvdata { void __iomem *base; @@ -121,6 +168,7 @@ struct tmc_drvdata { enum tmc_config_type config_type; enum tmc_mem_intf_width memwidth; u32 trigger_cntr; + u32 etr_caps; }; /* Generic functions */ @@ -139,4 +187,39 @@ extern const struct coresight_ops tmc_etf_cs_ops; int tmc_read_prepare_etr(struct tmc_drvdata *drvdata); int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata); extern const struct coresight_ops tmc_etr_cs_ops; + + +#define TMC_REG_PAIR(name, lo_off, hi_off) \ +static inline u64 \ +tmc_read_##name(struct tmc_drvdata *drvdata) \ +{ \ + return coresight_read_reg_pair(drvdata->base, lo_off, hi_off); \ +} \ +static inline void \ +tmc_write_##name(struct tmc_drvdata *drvdata, u64 val) \ +{ \ + coresight_write_reg_pair(drvdata->base, val, lo_off, hi_off); \ +} + +TMC_REG_PAIR(rrp, TMC_RRP, TMC_RRPHI) +TMC_REG_PAIR(rwp, TMC_RWP, TMC_RWPHI) +TMC_REG_PAIR(dba, TMC_DBALO, TMC_DBAHI) + +/* Initialise the caps from unadvertised static capabilities of the device */ +static inline void tmc_etr_init_caps(struct tmc_drvdata *drvdata, u32 dev_caps) +{ + WARN_ON(drvdata->etr_caps); + drvdata->etr_caps = dev_caps; +} + +static inline void tmc_etr_set_cap(struct tmc_drvdata *drvdata, u32 cap) +{ + drvdata->etr_caps |= cap; +} + +static inline bool tmc_etr_has_cap(struct tmc_drvdata *drvdata, u32 cap) +{ + return !!(drvdata->etr_caps & cap); +} + #endif diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 0673baf0f2f5..d7a3e453016d 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -192,7 +192,7 @@ static const struct dev_pm_ops tpiu_dev_pm_ops = { SET_RUNTIME_PM_OPS(tpiu_runtime_suspend, tpiu_runtime_resume, NULL) }; -static struct amba_id tpiu_ids[] = { +static const struct amba_id tpiu_ids[] = { { .id = 0x0003b912, .mask = 0x0003ffff, @@ -201,6 +201,11 @@ static struct amba_id tpiu_ids[] = { .id = 0x0004b912, .mask = 0x0007ffff, }, + { + /* Coresight SoC-600 */ + .id = 0x000bb9e7, + .mask = 0x000fffff, + }, { 0, 0}, }; diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 6a0202b7384f..b8091bef21dc 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -53,6 +53,14 @@ static DEFINE_PER_CPU(struct list_head *, tracer_path); */ static struct list_head *stm_path; +/* + * When losing synchronisation a new barrier packet needs to be inserted at the + * beginning of the data collected in a buffer. That way the decoder knows that + * it needs to look for another sync sequence. + */ +const u32 barrier_pkt[5] = {0x7fffffff, 0x7fffffff, + 0x7fffffff, 0x7fffffff, 0x0}; + static int coresight_id_match(struct device *dev, void *data) { int trace_id, i_trace_id; |