1052 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.4 *5 * Description: CoreSight Program Flow Trace driver6 */7 8#include <linux/kernel.h>9#include <linux/moduleparam.h>10#include <linux/init.h>11#include <linux/types.h>12#include <linux/device.h>13#include <linux/io.h>14#include <linux/err.h>15#include <linux/fs.h>16#include <linux/slab.h>17#include <linux/delay.h>18#include <linux/smp.h>19#include <linux/sysfs.h>20#include <linux/stat.h>21#include <linux/pm_runtime.h>22#include <linux/cpu.h>23#include <linux/of.h>24#include <linux/coresight.h>25#include <linux/coresight-pmu.h>26#include <linux/amba/bus.h>27#include <linux/seq_file.h>28#include <linux/uaccess.h>29#include <linux/clk.h>30#include <linux/perf_event.h>31#include <asm/sections.h>32 33#include "coresight-etm.h"34#include "coresight-etm-perf.h"35#include "coresight-trace-id.h"36 37/*38 * Not really modular but using module_param is the easiest way to39 * remain consistent with existing use cases for now.40 */41static int boot_enable;42module_param_named(boot_enable, boot_enable, int, S_IRUGO);43 44static struct etm_drvdata *etmdrvdata[NR_CPUS];45 46static enum cpuhp_state hp_online;47 48/*49 * Memory mapped writes to clear os lock are not supported on some processors50 * and OS lock must be unlocked before any memory mapped access on such51 * processors, otherwise memory mapped reads/writes will be invalid.52 */53static void etm_os_unlock(struct etm_drvdata *drvdata)54{55 /* Writing any value to ETMOSLAR unlocks the trace registers */56 etm_writel(drvdata, 0x0, ETMOSLAR);57 drvdata->os_unlock = true;58 isb();59}60 61static void etm_set_pwrdwn(struct etm_drvdata *drvdata)62{63 u32 etmcr;64 65 /* Ensure pending cp14 accesses complete before setting pwrdwn */66 mb();67 isb();68 etmcr = etm_readl(drvdata, ETMCR);69 etmcr |= ETMCR_PWD_DWN;70 etm_writel(drvdata, etmcr, ETMCR);71}72 73static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)74{75 u32 etmcr;76 77 etmcr = etm_readl(drvdata, ETMCR);78 etmcr &= ~ETMCR_PWD_DWN;79 etm_writel(drvdata, etmcr, ETMCR);80 /* Ensure pwrup completes before subsequent cp14 accesses */81 mb();82 isb();83}84 85static void etm_set_pwrup(struct etm_drvdata *drvdata)86{87 u32 etmpdcr;88 89 etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);90 etmpdcr |= ETMPDCR_PWD_UP;91 writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);92 /* Ensure pwrup completes before subsequent cp14 accesses */93 mb();94 isb();95}96 97static void etm_clr_pwrup(struct etm_drvdata *drvdata)98{99 u32 etmpdcr;100 101 /* Ensure pending cp14 accesses complete before clearing pwrup */102 mb();103 isb();104 etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);105 etmpdcr &= ~ETMPDCR_PWD_UP;106 writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);107}108 109/**110 * coresight_timeout_etm - loop until a bit has changed to a specific state.111 * @drvdata: etm's private data structure.112 * @offset: address of a register, starting from @addr.113 * @position: the position of the bit of interest.114 * @value: the value the bit should have.115 *116 * Basically the same as @coresight_timeout except for the register access117 * method where we have to account for CP14 configurations.118 *119 * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if120 * TIMEOUT_US has elapsed, which ever happens first.121 */122 123static int coresight_timeout_etm(struct etm_drvdata *drvdata, u32 offset,124 int position, int value)125{126 int i;127 u32 val;128 129 for (i = TIMEOUT_US; i > 0; i--) {130 val = etm_readl(drvdata, offset);131 /* Waiting on the bit to go from 0 to 1 */132 if (value) {133 if (val & BIT(position))134 return 0;135 /* Waiting on the bit to go from 1 to 0 */136 } else {137 if (!(val & BIT(position)))138 return 0;139 }140 141 /*142 * Delay is arbitrary - the specification doesn't say how long143 * we are expected to wait. Extra check required to make sure144 * we don't wait needlessly on the last iteration.145 */146 if (i - 1)147 udelay(1);148 }149 150 return -EAGAIN;151}152 153 154static void etm_set_prog(struct etm_drvdata *drvdata)155{156 u32 etmcr;157 158 etmcr = etm_readl(drvdata, ETMCR);159 etmcr |= ETMCR_ETM_PRG;160 etm_writel(drvdata, etmcr, ETMCR);161 /*162 * Recommended by spec for cp14 accesses to ensure etmcr write is163 * complete before polling etmsr164 */165 isb();166 if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 1)) {167 dev_err(&drvdata->csdev->dev,168 "%s: timeout observed when probing at offset %#x\n",169 __func__, ETMSR);170 }171}172 173static void etm_clr_prog(struct etm_drvdata *drvdata)174{175 u32 etmcr;176 177 etmcr = etm_readl(drvdata, ETMCR);178 etmcr &= ~ETMCR_ETM_PRG;179 etm_writel(drvdata, etmcr, ETMCR);180 /*181 * Recommended by spec for cp14 accesses to ensure etmcr write is182 * complete before polling etmsr183 */184 isb();185 if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 0)) {186 dev_err(&drvdata->csdev->dev,187 "%s: timeout observed when probing at offset %#x\n",188 __func__, ETMSR);189 }190}191 192void etm_set_default(struct etm_config *config)193{194 int i;195 196 if (WARN_ON_ONCE(!config))197 return;198 199 /*200 * Taken verbatim from the TRM:201 *202 * To trace all memory:203 * set bit [24] in register 0x009, the ETMTECR1, to 1204 * set all other bits in register 0x009, the ETMTECR1, to 0205 * set all bits in register 0x007, the ETMTECR2, to 0206 * set register 0x008, the ETMTEEVR, to 0x6F (TRUE).207 */208 config->enable_ctrl1 = ETMTECR1_INC_EXC;209 config->enable_ctrl2 = 0x0;210 config->enable_event = ETM_HARD_WIRE_RES_A;211 212 config->trigger_event = ETM_DEFAULT_EVENT_VAL;213 config->enable_event = ETM_HARD_WIRE_RES_A;214 215 config->seq_12_event = ETM_DEFAULT_EVENT_VAL;216 config->seq_21_event = ETM_DEFAULT_EVENT_VAL;217 config->seq_23_event = ETM_DEFAULT_EVENT_VAL;218 config->seq_31_event = ETM_DEFAULT_EVENT_VAL;219 config->seq_32_event = ETM_DEFAULT_EVENT_VAL;220 config->seq_13_event = ETM_DEFAULT_EVENT_VAL;221 config->timestamp_event = ETM_DEFAULT_EVENT_VAL;222 223 for (i = 0; i < ETM_MAX_CNTR; i++) {224 config->cntr_rld_val[i] = 0x0;225 config->cntr_event[i] = ETM_DEFAULT_EVENT_VAL;226 config->cntr_rld_event[i] = ETM_DEFAULT_EVENT_VAL;227 config->cntr_val[i] = 0x0;228 }229 230 config->seq_curr_state = 0x0;231 config->ctxid_idx = 0x0;232 for (i = 0; i < ETM_MAX_CTXID_CMP; i++)233 config->ctxid_pid[i] = 0x0;234 235 config->ctxid_mask = 0x0;236 /* Setting default to 1024 as per TRM recommendation */237 config->sync_freq = 0x400;238}239 240void etm_config_trace_mode(struct etm_config *config)241{242 u32 flags, mode;243 244 mode = config->mode;245 246 mode &= (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER);247 248 /* excluding kernel AND user space doesn't make sense */249 if (mode == (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))250 return;251 252 /* nothing to do if neither flags are set */253 if (!(mode & ETM_MODE_EXCL_KERN) && !(mode & ETM_MODE_EXCL_USER))254 return;255 256 flags = (1 << 0 | /* instruction execute */257 3 << 3 | /* ARM instruction */258 0 << 5 | /* No data value comparison */259 0 << 7 | /* No exact mach */260 0 << 8); /* Ignore context ID */261 262 /* No need to worry about single address comparators. */263 config->enable_ctrl2 = 0x0;264 265 /* Bit 0 is address range comparator 1 */266 config->enable_ctrl1 = ETMTECR1_ADDR_COMP_1;267 268 /*269 * On ETMv3.5:270 * ETMACTRn[13,11] == Non-secure state comparison control271 * ETMACTRn[12,10] == Secure state comparison control272 *273 * b00 == Match in all modes in this state274 * b01 == Do not match in any more in this state275 * b10 == Match in all modes excepts user mode in this state276 * b11 == Match only in user mode in this state277 */278 279 /* Tracing in secure mode is not supported at this time */280 flags |= (0 << 12 | 1 << 10);281 282 if (mode & ETM_MODE_EXCL_USER) {283 /* exclude user, match all modes except user mode */284 flags |= (1 << 13 | 0 << 11);285 } else {286 /* exclude kernel, match only in user mode */287 flags |= (1 << 13 | 1 << 11);288 }289 290 /*291 * The ETMEEVR register is already set to "hard wire A". As such292 * all there is to do is setup an address comparator that spans293 * the entire address range and configure the state and mode bits.294 */295 config->addr_val[0] = (u32) 0x0;296 config->addr_val[1] = (u32) ~0x0;297 config->addr_acctype[0] = flags;298 config->addr_acctype[1] = flags;299 config->addr_type[0] = ETM_ADDR_TYPE_RANGE;300 config->addr_type[1] = ETM_ADDR_TYPE_RANGE;301}302 303#define ETM3X_SUPPORTED_OPTIONS (ETMCR_CYC_ACC | \304 ETMCR_TIMESTAMP_EN | \305 ETMCR_RETURN_STACK)306 307static int etm_parse_event_config(struct etm_drvdata *drvdata,308 struct perf_event *event)309{310 struct etm_config *config = &drvdata->config;311 struct perf_event_attr *attr = &event->attr;312 313 if (!attr)314 return -EINVAL;315 316 /* Clear configuration from previous run */317 memset(config, 0, sizeof(struct etm_config));318 319 if (attr->exclude_kernel)320 config->mode = ETM_MODE_EXCL_KERN;321 322 if (attr->exclude_user)323 config->mode = ETM_MODE_EXCL_USER;324 325 /* Always start from the default config */326 etm_set_default(config);327 328 /*329 * By default the tracers are configured to trace the whole address330 * range. Narrow the field only if requested by user space.331 */332 if (config->mode)333 etm_config_trace_mode(config);334 335 /*336 * At this time only cycle accurate, return stack and timestamp337 * options are available.338 */339 if (attr->config & ~ETM3X_SUPPORTED_OPTIONS)340 return -EINVAL;341 342 config->ctrl = attr->config;343 344 /* Don't trace contextID when runs in non-root PID namespace */345 if (!task_is_in_init_pid_ns(current))346 config->ctrl &= ~ETMCR_CTXID_SIZE;347 348 /*349 * Possible to have cores with PTM (supports ret stack) and ETM350 * (never has ret stack) on the same SoC. So if we have a request351 * for return stack that can't be honoured on this core then352 * clear the bit - trace will still continue normally353 */354 if ((config->ctrl & ETMCR_RETURN_STACK) &&355 !(drvdata->etmccer & ETMCCER_RETSTACK))356 config->ctrl &= ~ETMCR_RETURN_STACK;357 358 return 0;359}360 361static int etm_enable_hw(struct etm_drvdata *drvdata)362{363 int i, rc;364 u32 etmcr;365 struct etm_config *config = &drvdata->config;366 struct coresight_device *csdev = drvdata->csdev;367 368 CS_UNLOCK(drvdata->base);369 370 rc = coresight_claim_device_unlocked(csdev);371 if (rc)372 goto done;373 374 /* Turn engine on */375 etm_clr_pwrdwn(drvdata);376 /* Apply power to trace registers */377 etm_set_pwrup(drvdata);378 /* Make sure all registers are accessible */379 etm_os_unlock(drvdata);380 381 etm_set_prog(drvdata);382 383 etmcr = etm_readl(drvdata, ETMCR);384 /* Clear setting from a previous run if need be */385 etmcr &= ~ETM3X_SUPPORTED_OPTIONS;386 etmcr |= drvdata->port_size;387 etmcr |= ETMCR_ETM_EN;388 etm_writel(drvdata, config->ctrl | etmcr, ETMCR);389 etm_writel(drvdata, config->trigger_event, ETMTRIGGER);390 etm_writel(drvdata, config->startstop_ctrl, ETMTSSCR);391 etm_writel(drvdata, config->enable_event, ETMTEEVR);392 etm_writel(drvdata, config->enable_ctrl1, ETMTECR1);393 etm_writel(drvdata, config->fifofull_level, ETMFFLR);394 for (i = 0; i < drvdata->nr_addr_cmp; i++) {395 etm_writel(drvdata, config->addr_val[i], ETMACVRn(i));396 etm_writel(drvdata, config->addr_acctype[i], ETMACTRn(i));397 }398 for (i = 0; i < drvdata->nr_cntr; i++) {399 etm_writel(drvdata, config->cntr_rld_val[i], ETMCNTRLDVRn(i));400 etm_writel(drvdata, config->cntr_event[i], ETMCNTENRn(i));401 etm_writel(drvdata, config->cntr_rld_event[i],402 ETMCNTRLDEVRn(i));403 etm_writel(drvdata, config->cntr_val[i], ETMCNTVRn(i));404 }405 etm_writel(drvdata, config->seq_12_event, ETMSQ12EVR);406 etm_writel(drvdata, config->seq_21_event, ETMSQ21EVR);407 etm_writel(drvdata, config->seq_23_event, ETMSQ23EVR);408 etm_writel(drvdata, config->seq_31_event, ETMSQ31EVR);409 etm_writel(drvdata, config->seq_32_event, ETMSQ32EVR);410 etm_writel(drvdata, config->seq_13_event, ETMSQ13EVR);411 etm_writel(drvdata, config->seq_curr_state, ETMSQR);412 for (i = 0; i < drvdata->nr_ext_out; i++)413 etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i));414 for (i = 0; i < drvdata->nr_ctxid_cmp; i++)415 etm_writel(drvdata, config->ctxid_pid[i], ETMCIDCVRn(i));416 etm_writel(drvdata, config->ctxid_mask, ETMCIDCMR);417 etm_writel(drvdata, config->sync_freq, ETMSYNCFR);418 /* No external input selected */419 etm_writel(drvdata, 0x0, ETMEXTINSELR);420 etm_writel(drvdata, config->timestamp_event, ETMTSEVR);421 /* No auxiliary control selected */422 etm_writel(drvdata, 0x0, ETMAUXCR);423 etm_writel(drvdata, drvdata->traceid, ETMTRACEIDR);424 /* No VMID comparator value selected */425 etm_writel(drvdata, 0x0, ETMVMIDCVR);426 427 etm_clr_prog(drvdata);428 429done:430 CS_LOCK(drvdata->base);431 432 dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n",433 drvdata->cpu, rc);434 return rc;435}436 437struct etm_enable_arg {438 struct etm_drvdata *drvdata;439 int rc;440};441 442static void etm_enable_hw_smp_call(void *info)443{444 struct etm_enable_arg *arg = info;445 446 if (WARN_ON(!arg))447 return;448 arg->rc = etm_enable_hw(arg->drvdata);449}450 451static int etm_cpu_id(struct coresight_device *csdev)452{453 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);454 455 return drvdata->cpu;456}457 458int etm_read_alloc_trace_id(struct etm_drvdata *drvdata)459{460 int trace_id;461 462 /*463 * This will allocate a trace ID to the cpu,464 * or return the one currently allocated.465 *466 * trace id function has its own lock467 */468 trace_id = coresight_trace_id_get_cpu_id(drvdata->cpu);469 if (IS_VALID_CS_TRACE_ID(trace_id))470 drvdata->traceid = (u8)trace_id;471 else472 dev_err(&drvdata->csdev->dev,473 "Failed to allocate trace ID for %s on CPU%d\n",474 dev_name(&drvdata->csdev->dev), drvdata->cpu);475 return trace_id;476}477 478void etm_release_trace_id(struct etm_drvdata *drvdata)479{480 coresight_trace_id_put_cpu_id(drvdata->cpu);481}482 483static int etm_enable_perf(struct coresight_device *csdev,484 struct perf_event *event,485 struct coresight_trace_id_map *id_map)486{487 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);488 int trace_id;489 490 if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))491 return -EINVAL;492 493 /* Configure the tracer based on the session's specifics */494 etm_parse_event_config(drvdata, event);495 496 /*497 * perf allocates cpu ids as part of _setup_aux() - device needs to use498 * the allocated ID. This reads the current version without allocation.499 *500 * This does not use the trace id lock to prevent lock_dep issues501 * with perf locks - we know the ID cannot change until perf shuts down502 * the session503 */504 trace_id = coresight_trace_id_read_cpu_id_map(drvdata->cpu, id_map);505 if (!IS_VALID_CS_TRACE_ID(trace_id)) {506 dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",507 dev_name(&drvdata->csdev->dev), drvdata->cpu);508 return -EINVAL;509 }510 drvdata->traceid = (u8)trace_id;511 512 /* And enable it */513 return etm_enable_hw(drvdata);514}515 516static int etm_enable_sysfs(struct coresight_device *csdev)517{518 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);519 struct etm_enable_arg arg = { };520 int ret;521 522 spin_lock(&drvdata->spinlock);523 524 /* sysfs needs to allocate and set a trace ID */525 ret = etm_read_alloc_trace_id(drvdata);526 if (ret < 0)527 goto unlock_enable_sysfs;528 529 /*530 * Configure the ETM only if the CPU is online. If it isn't online531 * hw configuration will take place on the local CPU during bring up.532 */533 if (cpu_online(drvdata->cpu)) {534 arg.drvdata = drvdata;535 ret = smp_call_function_single(drvdata->cpu,536 etm_enable_hw_smp_call, &arg, 1);537 if (!ret)538 ret = arg.rc;539 if (!ret)540 drvdata->sticky_enable = true;541 } else {542 ret = -ENODEV;543 }544 545 if (ret)546 etm_release_trace_id(drvdata);547 548unlock_enable_sysfs:549 spin_unlock(&drvdata->spinlock);550 551 if (!ret)552 dev_dbg(&csdev->dev, "ETM tracing enabled\n");553 return ret;554}555 556static int etm_enable(struct coresight_device *csdev, struct perf_event *event,557 enum cs_mode mode, struct coresight_trace_id_map *id_map)558{559 int ret;560 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);561 562 if (!coresight_take_mode(csdev, mode)) {563 /* Someone is already using the tracer */564 return -EBUSY;565 }566 567 switch (mode) {568 case CS_MODE_SYSFS:569 ret = etm_enable_sysfs(csdev);570 break;571 case CS_MODE_PERF:572 ret = etm_enable_perf(csdev, event, id_map);573 break;574 default:575 ret = -EINVAL;576 }577 578 /* The tracer didn't start */579 if (ret)580 coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);581 582 return ret;583}584 585static void etm_disable_hw(void *info)586{587 int i;588 struct etm_drvdata *drvdata = info;589 struct etm_config *config = &drvdata->config;590 struct coresight_device *csdev = drvdata->csdev;591 592 CS_UNLOCK(drvdata->base);593 etm_set_prog(drvdata);594 595 /* Read back sequencer and counters for post trace analysis */596 config->seq_curr_state = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);597 598 for (i = 0; i < drvdata->nr_cntr; i++)599 config->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));600 601 etm_set_pwrdwn(drvdata);602 coresight_disclaim_device_unlocked(csdev);603 604 CS_LOCK(drvdata->base);605 606 dev_dbg(&drvdata->csdev->dev,607 "cpu: %d disable smp call done\n", drvdata->cpu);608}609 610static void etm_disable_perf(struct coresight_device *csdev)611{612 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);613 614 if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))615 return;616 617 CS_UNLOCK(drvdata->base);618 619 /* Setting the prog bit disables tracing immediately */620 etm_set_prog(drvdata);621 622 /*623 * There is no way to know when the tracer will be used again so624 * power down the tracer.625 */626 etm_set_pwrdwn(drvdata);627 coresight_disclaim_device_unlocked(csdev);628 629 CS_LOCK(drvdata->base);630 631 /*632 * perf will release trace ids when _free_aux()633 * is called at the end of the session634 */635 636}637 638static void etm_disable_sysfs(struct coresight_device *csdev)639{640 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);641 642 /*643 * Taking hotplug lock here protects from clocks getting disabled644 * with tracing being left on (crash scenario) if user disable occurs645 * after cpu online mask indicates the cpu is offline but before the646 * DYING hotplug callback is serviced by the ETM driver.647 */648 cpus_read_lock();649 spin_lock(&drvdata->spinlock);650 651 /*652 * Executing etm_disable_hw on the cpu whose ETM is being disabled653 * ensures that register writes occur when cpu is powered.654 */655 smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1);656 657 spin_unlock(&drvdata->spinlock);658 cpus_read_unlock();659 660 /*661 * we only release trace IDs when resetting sysfs.662 * This permits sysfs users to read the trace ID after the trace663 * session has completed. This maintains operational behaviour with664 * prior trace id allocation method665 */666 667 dev_dbg(&csdev->dev, "ETM tracing disabled\n");668}669 670static void etm_disable(struct coresight_device *csdev,671 struct perf_event *event)672{673 enum cs_mode mode;674 675 /*676 * For as long as the tracer isn't disabled another entity can't677 * change its status. As such we can read the status here without678 * fearing it will change under us.679 */680 mode = coresight_get_mode(csdev);681 682 switch (mode) {683 case CS_MODE_DISABLED:684 break;685 case CS_MODE_SYSFS:686 etm_disable_sysfs(csdev);687 break;688 case CS_MODE_PERF:689 etm_disable_perf(csdev);690 break;691 default:692 WARN_ON_ONCE(mode);693 return;694 }695 696 if (mode)697 coresight_set_mode(csdev, CS_MODE_DISABLED);698}699 700static const struct coresight_ops_source etm_source_ops = {701 .cpu_id = etm_cpu_id,702 .enable = etm_enable,703 .disable = etm_disable,704};705 706static const struct coresight_ops etm_cs_ops = {707 .source_ops = &etm_source_ops,708};709 710static int etm_online_cpu(unsigned int cpu)711{712 if (!etmdrvdata[cpu])713 return 0;714 715 if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable)716 coresight_enable_sysfs(etmdrvdata[cpu]->csdev);717 return 0;718}719 720static int etm_starting_cpu(unsigned int cpu)721{722 if (!etmdrvdata[cpu])723 return 0;724 725 spin_lock(&etmdrvdata[cpu]->spinlock);726 if (!etmdrvdata[cpu]->os_unlock) {727 etm_os_unlock(etmdrvdata[cpu]);728 etmdrvdata[cpu]->os_unlock = true;729 }730 731 if (coresight_get_mode(etmdrvdata[cpu]->csdev))732 etm_enable_hw(etmdrvdata[cpu]);733 spin_unlock(&etmdrvdata[cpu]->spinlock);734 return 0;735}736 737static int etm_dying_cpu(unsigned int cpu)738{739 if (!etmdrvdata[cpu])740 return 0;741 742 spin_lock(&etmdrvdata[cpu]->spinlock);743 if (coresight_get_mode(etmdrvdata[cpu]->csdev))744 etm_disable_hw(etmdrvdata[cpu]);745 spin_unlock(&etmdrvdata[cpu]->spinlock);746 return 0;747}748 749static bool etm_arch_supported(u8 arch)750{751 switch (arch) {752 case ETM_ARCH_V3_3:753 break;754 case ETM_ARCH_V3_5:755 break;756 case PFT_ARCH_V1_0:757 break;758 case PFT_ARCH_V1_1:759 break;760 default:761 return false;762 }763 return true;764}765 766static void etm_init_arch_data(void *info)767{768 u32 etmidr;769 u32 etmccr;770 struct etm_drvdata *drvdata = info;771 772 /* Make sure all registers are accessible */773 etm_os_unlock(drvdata);774 775 CS_UNLOCK(drvdata->base);776 777 /* First dummy read */778 (void)etm_readl(drvdata, ETMPDSR);779 /* Provide power to ETM: ETMPDCR[3] == 1 */780 etm_set_pwrup(drvdata);781 /*782 * Clear power down bit since when this bit is set writes to783 * certain registers might be ignored.784 */785 etm_clr_pwrdwn(drvdata);786 /*787 * Set prog bit. It will be set from reset but this is included to788 * ensure it is set789 */790 etm_set_prog(drvdata);791 792 /* Find all capabilities */793 etmidr = etm_readl(drvdata, ETMIDR);794 drvdata->arch = BMVAL(etmidr, 4, 11);795 drvdata->port_size = etm_readl(drvdata, ETMCR) & PORT_SIZE_MASK;796 797 drvdata->etmccer = etm_readl(drvdata, ETMCCER);798 etmccr = etm_readl(drvdata, ETMCCR);799 drvdata->etmccr = etmccr;800 drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;801 drvdata->nr_cntr = BMVAL(etmccr, 13, 15);802 drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);803 drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);804 drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);805 806 etm_set_pwrdwn(drvdata);807 etm_clr_pwrup(drvdata);808 CS_LOCK(drvdata->base);809}810 811static int __init etm_hp_setup(void)812{813 int ret;814 815 ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING,816 "arm/coresight:starting",817 etm_starting_cpu, etm_dying_cpu);818 819 if (ret)820 return ret;821 822 ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN,823 "arm/coresight:online",824 etm_online_cpu, NULL);825 826 /* HP dyn state ID returned in ret on success */827 if (ret > 0) {828 hp_online = ret;829 return 0;830 }831 832 /* failed dyn state - remove others */833 cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);834 835 return ret;836}837 838static void etm_hp_clear(void)839{840 cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);841 if (hp_online) {842 cpuhp_remove_state_nocalls(hp_online);843 hp_online = 0;844 }845}846 847static int etm_probe(struct amba_device *adev, const struct amba_id *id)848{849 int ret;850 void __iomem *base;851 struct device *dev = &adev->dev;852 struct coresight_platform_data *pdata = NULL;853 struct etm_drvdata *drvdata;854 struct resource *res = &adev->res;855 struct coresight_desc desc = { 0 };856 857 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);858 if (!drvdata)859 return -ENOMEM;860 861 drvdata->use_cp14 = fwnode_property_read_bool(dev->fwnode, "arm,cp14");862 dev_set_drvdata(dev, drvdata);863 864 /* Validity for the resource is already checked by the AMBA core */865 base = devm_ioremap_resource(dev, res);866 if (IS_ERR(base))867 return PTR_ERR(base);868 869 drvdata->base = base;870 desc.access = CSDEV_ACCESS_IOMEM(base);871 872 spin_lock_init(&drvdata->spinlock);873 874 drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */875 if (!IS_ERR(drvdata->atclk)) {876 ret = clk_prepare_enable(drvdata->atclk);877 if (ret)878 return ret;879 }880 881 drvdata->cpu = coresight_get_cpu(dev);882 if (drvdata->cpu < 0)883 return drvdata->cpu;884 885 desc.name = devm_kasprintf(dev, GFP_KERNEL, "etm%d", drvdata->cpu);886 if (!desc.name)887 return -ENOMEM;888 889 if (smp_call_function_single(drvdata->cpu,890 etm_init_arch_data, drvdata, 1))891 dev_err(dev, "ETM arch init failed\n");892 893 if (etm_arch_supported(drvdata->arch) == false)894 return -EINVAL;895 896 etm_set_default(&drvdata->config);897 898 pdata = coresight_get_platform_data(dev);899 if (IS_ERR(pdata))900 return PTR_ERR(pdata);901 902 adev->dev.platform_data = pdata;903 904 desc.type = CORESIGHT_DEV_TYPE_SOURCE;905 desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;906 desc.ops = &etm_cs_ops;907 desc.pdata = pdata;908 desc.dev = dev;909 desc.groups = coresight_etm_groups;910 drvdata->csdev = coresight_register(&desc);911 if (IS_ERR(drvdata->csdev))912 return PTR_ERR(drvdata->csdev);913 914 ret = etm_perf_symlink(drvdata->csdev, true);915 if (ret) {916 coresight_unregister(drvdata->csdev);917 return ret;918 }919 920 etmdrvdata[drvdata->cpu] = drvdata;921 922 pm_runtime_put(&adev->dev);923 dev_info(&drvdata->csdev->dev,924 "%s initialized\n", (char *)coresight_get_uci_data(id));925 if (boot_enable) {926 coresight_enable_sysfs(drvdata->csdev);927 drvdata->boot_enable = true;928 }929 930 return 0;931}932 933static void clear_etmdrvdata(void *info)934{935 int cpu = *(int *)info;936 937 etmdrvdata[cpu] = NULL;938}939 940static void etm_remove(struct amba_device *adev)941{942 struct etm_drvdata *drvdata = dev_get_drvdata(&adev->dev);943 944 etm_perf_symlink(drvdata->csdev, false);945 946 /*947 * Taking hotplug lock here to avoid racing between etm_remove and948 * CPU hotplug call backs.949 */950 cpus_read_lock();951 /*952 * The readers for etmdrvdata[] are CPU hotplug call backs953 * and PM notification call backs. Change etmdrvdata[i] on954 * CPU i ensures these call backs has consistent view955 * inside one call back function.956 */957 if (smp_call_function_single(drvdata->cpu, clear_etmdrvdata, &drvdata->cpu, 1))958 etmdrvdata[drvdata->cpu] = NULL;959 960 cpus_read_unlock();961 962 coresight_unregister(drvdata->csdev);963}964 965#ifdef CONFIG_PM966static int etm_runtime_suspend(struct device *dev)967{968 struct etm_drvdata *drvdata = dev_get_drvdata(dev);969 970 if (drvdata && !IS_ERR(drvdata->atclk))971 clk_disable_unprepare(drvdata->atclk);972 973 return 0;974}975 976static int etm_runtime_resume(struct device *dev)977{978 struct etm_drvdata *drvdata = dev_get_drvdata(dev);979 980 if (drvdata && !IS_ERR(drvdata->atclk))981 clk_prepare_enable(drvdata->atclk);982 983 return 0;984}985#endif986 987static const struct dev_pm_ops etm_dev_pm_ops = {988 SET_RUNTIME_PM_OPS(etm_runtime_suspend, etm_runtime_resume, NULL)989};990 991static const struct amba_id etm_ids[] = {992 /* ETM 3.3 */993 CS_AMBA_ID_DATA(0x000bb921, "ETM 3.3"),994 /* ETM 3.5 - Cortex-A5 */995 CS_AMBA_ID_DATA(0x000bb955, "ETM 3.5"),996 /* ETM 3.5 */997 CS_AMBA_ID_DATA(0x000bb956, "ETM 3.5"),998 /* PTM 1.0 */999 CS_AMBA_ID_DATA(0x000bb950, "PTM 1.0"),1000 /* PTM 1.1 */1001 CS_AMBA_ID_DATA(0x000bb95f, "PTM 1.1"),1002 /* PTM 1.1 Qualcomm */1003 CS_AMBA_ID_DATA(0x000b006f, "PTM 1.1"),1004 { 0, 0, NULL},1005};1006 1007MODULE_DEVICE_TABLE(amba, etm_ids);1008 1009static struct amba_driver etm_driver = {1010 .drv = {1011 .name = "coresight-etm3x",1012 .pm = &etm_dev_pm_ops,1013 .suppress_bind_attrs = true,1014 },1015 .probe = etm_probe,1016 .remove = etm_remove,1017 .id_table = etm_ids,1018};1019 1020static int __init etm_init(void)1021{1022 int ret;1023 1024 ret = etm_hp_setup();1025 1026 /* etm_hp_setup() does its own cleanup - exit on error */1027 if (ret)1028 return ret;1029 1030 ret = amba_driver_register(&etm_driver);1031 if (ret) {1032 pr_err("Error registering etm3x driver\n");1033 etm_hp_clear();1034 }1035 1036 return ret;1037}1038 1039static void __exit etm_exit(void)1040{1041 amba_driver_unregister(&etm_driver);1042 etm_hp_clear();1043}1044 1045module_init(etm_init);1046module_exit(etm_exit);1047 1048MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");1049MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");1050MODULE_DESCRIPTION("Arm CoreSight Program Flow Trace driver");1051MODULE_LICENSE("GPL v2");1052