NULL,
 };
 
+struct etmv4_reg {
+       void __iomem *addr;
+       u32 data;
+};
+
+static void do_smp_cross_read(void *data)
+{
+       struct etmv4_reg *reg = data;
+
+       reg->data = readl_relaxed(reg->addr);
+}
+
+static u32 etmv4_cross_read(const struct device *dev, u32 offset)
+{
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
+       struct etmv4_reg reg;
+
+       reg.addr = drvdata->base + offset;
+       /*
+        * smp cross call ensures the CPU will be powered up before
+        * accessing the ETMv4 trace core registers
+        */
+       smp_call_function_single(drvdata->cpu, do_smp_cross_read, ®, 1);
+       return reg.data;
+}
+
 #define coresight_etm4x_simple_func(name, offset)                      \
-       coresight_simple_func(struct etmv4_drvdata, name, offset)
+       coresight_simple_func(struct etmv4_drvdata, NULL, name, offset)
+
+#define coresight_etm4x_cross_read(name, offset)                       \
+       coresight_simple_func(struct etmv4_drvdata, etmv4_cross_read,   \
+                             name, offset)
 
-coresight_etm4x_simple_func(trcoslsr, TRCOSLSR);
 coresight_etm4x_simple_func(trcpdcr, TRCPDCR);
 coresight_etm4x_simple_func(trcpdsr, TRCPDSR);
 coresight_etm4x_simple_func(trclsr, TRCLSR);
-coresight_etm4x_simple_func(trcconfig, TRCCONFIGR);
-coresight_etm4x_simple_func(trctraceid, TRCTRACEIDR);
 coresight_etm4x_simple_func(trcauthstatus, TRCAUTHSTATUS);
 coresight_etm4x_simple_func(trcdevid, TRCDEVID);
 coresight_etm4x_simple_func(trcdevtype, TRCDEVTYPE);
 coresight_etm4x_simple_func(trcpidr1, TRCPIDR1);
 coresight_etm4x_simple_func(trcpidr2, TRCPIDR2);
 coresight_etm4x_simple_func(trcpidr3, TRCPIDR3);
+coresight_etm4x_cross_read(trcoslsr, TRCOSLSR);
+coresight_etm4x_cross_read(trcconfig, TRCCONFIGR);
+coresight_etm4x_cross_read(trctraceid, TRCTRACEIDR);
 
 static struct attribute *coresight_etmv4_mgmt_attrs[] = {
        &dev_attr_trcoslsr.attr,
        NULL,
 };
 
-coresight_etm4x_simple_func(trcidr0, TRCIDR0);
-coresight_etm4x_simple_func(trcidr1, TRCIDR1);
-coresight_etm4x_simple_func(trcidr2, TRCIDR2);
-coresight_etm4x_simple_func(trcidr3, TRCIDR3);
-coresight_etm4x_simple_func(trcidr4, TRCIDR4);
-coresight_etm4x_simple_func(trcidr5, TRCIDR5);
+coresight_etm4x_cross_read(trcidr0, TRCIDR0);
+coresight_etm4x_cross_read(trcidr1, TRCIDR1);
+coresight_etm4x_cross_read(trcidr2, TRCIDR2);
+coresight_etm4x_cross_read(trcidr3, TRCIDR3);
+coresight_etm4x_cross_read(trcidr4, TRCIDR4);
+coresight_etm4x_cross_read(trcidr5, TRCIDR5);
 /* trcidr[6,7] are reserved */
-coresight_etm4x_simple_func(trcidr8, TRCIDR8);
-coresight_etm4x_simple_func(trcidr9, TRCIDR9);
-coresight_etm4x_simple_func(trcidr10, TRCIDR10);
-coresight_etm4x_simple_func(trcidr11, TRCIDR11);
-coresight_etm4x_simple_func(trcidr12, TRCIDR12);
-coresight_etm4x_simple_func(trcidr13, TRCIDR13);
+coresight_etm4x_cross_read(trcidr8, TRCIDR8);
+coresight_etm4x_cross_read(trcidr9, TRCIDR9);
+coresight_etm4x_cross_read(trcidr10, TRCIDR10);
+coresight_etm4x_cross_read(trcidr11, TRCIDR11);
+coresight_etm4x_cross_read(trcidr12, TRCIDR12);
+coresight_etm4x_cross_read(trcidr13, TRCIDR13);
 
 static struct attribute *coresight_etmv4_trcidr_attrs[] = {
        &dev_attr_trcidr0.attr,
 
 #define ETM_MODE_EXCL_KERN     BIT(30)
 #define ETM_MODE_EXCL_USER     BIT(31)
 
-#define coresight_simple_func(type, name, offset)                      \
+typedef u32 (*coresight_read_fn)(const struct device *, u32 offset);
+#define coresight_simple_func(type, func, name, offset)                        \
 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;                                                        \
        pm_runtime_get_sync(_dev->parent);                              \
-       val = readl_relaxed(drvdata->base + offset);                    \
+       if (fn)                                                         \
+               val = fn(_dev->parent, offset);                         \
+       else                                                            \
+               val = readl_relaxed(drvdata->base + offset);            \
        pm_runtime_put_sync(_dev->parent);                              \
        return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);                \
 }                                                                      \