H A D | arm-ccn.c | 348 struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev)); arm_ccn_pmu_events_is_visible() local 354 if (event->type == CCN_TYPE_SBAS && !ccn->sbas_present) arm_ccn_pmu_events_is_visible() 356 if (event->type == CCN_TYPE_SBSX && !ccn->sbsx_present) arm_ccn_pmu_events_is_visible() 429 static u64 *arm_ccn_pmu_get_cmp_mask(struct arm_ccn *ccn, const char *name) arm_ccn_pmu_get_cmp_mask() argument 439 return &ccn->dt.cmp_mask[i].l; arm_ccn_pmu_get_cmp_mask() 441 return &ccn->dt.cmp_mask[i].h; arm_ccn_pmu_get_cmp_mask() 450 struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev)); arm_ccn_pmu_cmp_mask_show() local 451 u64 *mask = arm_ccn_pmu_get_cmp_mask(ccn, attr->attr.name); arm_ccn_pmu_cmp_mask_show() 459 struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev)); arm_ccn_pmu_cmp_mask_store() local 460 u64 *mask = arm_ccn_pmu_get_cmp_mask(ccn, attr->attr.name); arm_ccn_pmu_cmp_mask_store() 592 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_event_destroy() local 596 clear_bit(CCN_IDX_PMU_CYCLE_COUNTER, ccn->dt.pmu_counters_mask); arm_ccn_pmu_event_destroy() 599 ccn->dt.pmu_counters[hw->idx].source; arm_ccn_pmu_event_destroy() 607 clear_bit(hw->idx, ccn->dt.pmu_counters_mask); arm_ccn_pmu_event_destroy() 610 ccn->dt.pmu_counters[hw->idx].source = NULL; arm_ccn_pmu_event_destroy() 611 ccn->dt.pmu_counters[hw->idx].event = NULL; arm_ccn_pmu_event_destroy() 616 struct arm_ccn *ccn; arm_ccn_pmu_event_init() local 626 ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_event_init() 630 dev_warn(ccn->dev, "Sampling not supported!\n"); arm_ccn_pmu_event_init() 637 dev_warn(ccn->dev, "Can't exclude execution levels!\n"); arm_ccn_pmu_event_init() 642 dev_warn(ccn->dev, "Can't provide per-task data!\n"); arm_ccn_pmu_event_init() 653 if (node_xp >= ccn->num_xps) { arm_ccn_pmu_event_init() 654 dev_warn(ccn->dev, "Invalid XP ID %d!\n", node_xp); arm_ccn_pmu_event_init() 661 if (node_xp >= ccn->num_nodes) { arm_ccn_pmu_event_init() 662 dev_warn(ccn->dev, "Invalid node ID %d!\n", node_xp); arm_ccn_pmu_event_init() 665 if (!arm_ccn_pmu_type_eq(type, ccn->node[node_xp].type)) { arm_ccn_pmu_event_init() 666 dev_warn(ccn->dev, "Invalid type 0x%x for node %d!\n", arm_ccn_pmu_event_init() 685 dev_warn(ccn->dev, "Invalid port %d for node/XP %d!\n", arm_ccn_pmu_event_init() 690 dev_warn(ccn->dev, "Invalid vc %d for node/XP %d!\n", arm_ccn_pmu_event_init() 697 dev_warn(ccn->dev, "Invalid event 0x%x for node/XP %d!\n", arm_ccn_pmu_event_init() 717 ccn->dt.pmu_counters_mask)) arm_ccn_pmu_event_init() 721 ccn->dt.pmu_counters[CCN_IDX_PMU_CYCLE_COUNTER].event = event; arm_ccn_pmu_event_init() 727 hw->idx = arm_ccn_pmu_alloc_bit(ccn->dt.pmu_counters_mask, arm_ccn_pmu_event_init() 730 dev_warn(ccn->dev, "No more counters available!\n"); arm_ccn_pmu_event_init() 735 source = &ccn->xp[node_xp]; arm_ccn_pmu_event_init() 737 source = &ccn->node[node_xp]; arm_ccn_pmu_event_init() 738 ccn->dt.pmu_counters[hw->idx].source = source; arm_ccn_pmu_event_init() 748 dev_warn(ccn->dev, "No more event sources/watchpoints on node/XP %d!\n", arm_ccn_pmu_event_init() 750 clear_bit(hw->idx, ccn->dt.pmu_counters_mask); arm_ccn_pmu_event_init() 755 ccn->dt.pmu_counters[hw->idx].event = event; arm_ccn_pmu_event_init() 760 static u64 arm_ccn_pmu_read_counter(struct arm_ccn *ccn, int idx) arm_ccn_pmu_read_counter() argument 766 res = readq(ccn->dt.base + CCN_DT_PMCCNTR); arm_ccn_pmu_read_counter() 769 writel(0x1, ccn->dt.base + CCN_DT_PMSR_REQ); arm_ccn_pmu_read_counter() 770 while (!(readl(ccn->dt.base + CCN_DT_PMSR) & 0x1)) arm_ccn_pmu_read_counter() 772 writel(0x1, ccn->dt.base + CCN_DT_PMSR_CLR); arm_ccn_pmu_read_counter() 773 res = readl(ccn->dt.base + CCN_DT_PMCCNTRSR + 4) & 0xff; arm_ccn_pmu_read_counter() 775 res |= readl(ccn->dt.base + CCN_DT_PMCCNTRSR); arm_ccn_pmu_read_counter() 778 res = readl(ccn->dt.base + CCN_DT_PMEVCNT(idx)); arm_ccn_pmu_read_counter() 786 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_event_update() local 792 new_count = arm_ccn_pmu_read_counter(ccn, hw->idx); arm_ccn_pmu_event_update() 802 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_xp_dt_config() local 808 xp = &ccn->xp[CCN_CONFIG_XP(event->attr.config)]; arm_ccn_pmu_xp_dt_config() 810 xp = &ccn->xp[arm_ccn_node_to_xp( arm_ccn_pmu_xp_dt_config() 818 spin_lock(&ccn->dt.config_lock); arm_ccn_pmu_xp_dt_config() 826 spin_unlock(&ccn->dt.config_lock); arm_ccn_pmu_xp_dt_config() 831 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_event_start() local 835 arm_ccn_pmu_read_counter(ccn, hw->idx)); arm_ccn_pmu_event_start() 838 if (!ccn->irq_used) arm_ccn_pmu_event_start() 839 hrtimer_start(&ccn->dt.hrtimer, arm_ccn_pmu_timer_period(), arm_ccn_pmu_event_start() 848 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_event_stop() local 855 if (!ccn->irq_used) arm_ccn_pmu_event_stop() 856 hrtimer_cancel(&ccn->dt.hrtimer); arm_ccn_pmu_event_stop() 859 timeout = arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) + arm_ccn_pmu_event_stop() 860 ccn->num_xps; arm_ccn_pmu_event_stop() 861 while (arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) < arm_ccn_pmu_event_stop() 873 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_xp_watchpoint_config() local 876 ccn->dt.pmu_counters[hw->idx].source; arm_ccn_pmu_xp_watchpoint_config() 881 u64 mask_l = ccn->dt.cmp_mask[CCN_CONFIG_MASK(event->attr.config)].l; arm_ccn_pmu_xp_watchpoint_config() 882 u64 mask_h = ccn->dt.cmp_mask[CCN_CONFIG_MASK(event->attr.config)].h; arm_ccn_pmu_xp_watchpoint_config() 921 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_xp_event_config() local 924 ccn->dt.pmu_counters[hw->idx].source; arm_ccn_pmu_xp_event_config() 942 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_node_event_config() local 945 ccn->dt.pmu_counters[hw->idx].source; arm_ccn_pmu_node_event_config() 979 struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu); arm_ccn_pmu_event_config() local 992 spin_lock(&ccn->dt.config_lock); arm_ccn_pmu_event_config() 996 val = readl(ccn->dt.base + CCN_DT_ACTIVE_DSM + offset); arm_ccn_pmu_event_config() 1000 writel(val, ccn->dt.base + CCN_DT_ACTIVE_DSM + offset); arm_ccn_pmu_event_config() 1012 spin_unlock(&ccn->dt.config_lock); arm_ccn_pmu_event_config() 1084 static int arm_ccn_pmu_init(struct arm_ccn *ccn) arm_ccn_pmu_init() argument 1090 ccn->dt.base = ccn->base + CCN_REGION_SIZE; arm_ccn_pmu_init() 1091 spin_lock_init(&ccn->dt.config_lock); arm_ccn_pmu_init() 1092 writel(CCN_DT_PMOVSR_CLR__MASK, ccn->dt.base + CCN_DT_PMOVSR_CLR); arm_ccn_pmu_init() 1093 writel(CCN_DT_CTL__DT_EN, ccn->dt.base + CCN_DT_CTL); arm_ccn_pmu_init() 1095 ccn->dt.base + CCN_DT_PMCR); arm_ccn_pmu_init() 1096 writel(0x1, ccn->dt.base + CCN_DT_PMSR_CLR); arm_ccn_pmu_init() 1097 for (i = 0; i < ccn->num_xps; i++) { arm_ccn_pmu_init() 1098 writel(0, ccn->xp[i].base + CCN_XP_DT_CONFIG); arm_ccn_pmu_init() 1104 ccn->xp[i].base + CCN_XP_DT_CONTROL); arm_ccn_pmu_init() 1106 ccn->dt.cmp_mask[CCN_IDX_MASK_ANY].l = ~0; arm_ccn_pmu_init() 1107 ccn->dt.cmp_mask[CCN_IDX_MASK_ANY].h = ~0; arm_ccn_pmu_init() 1108 ccn->dt.cmp_mask[CCN_IDX_MASK_EXACT].l = 0; arm_ccn_pmu_init() 1109 ccn->dt.cmp_mask[CCN_IDX_MASK_EXACT].h = 0; arm_ccn_pmu_init() 1110 ccn->dt.cmp_mask[CCN_IDX_MASK_ORDER].l = ~0; arm_ccn_pmu_init() 1111 ccn->dt.cmp_mask[CCN_IDX_MASK_ORDER].h = ~(0x1 << 15); arm_ccn_pmu_init() 1112 ccn->dt.cmp_mask[CCN_IDX_MASK_OPCODE].l = ~0; arm_ccn_pmu_init() 1113 ccn->dt.cmp_mask[CCN_IDX_MASK_OPCODE].h = ~(0x1f << 9); arm_ccn_pmu_init() 1116 ccn->dt.id = ida_simple_get(&arm_ccn_pmu_ida, 0, 0, GFP_KERNEL); arm_ccn_pmu_init() 1117 if (ccn->dt.id == 0) { arm_ccn_pmu_init() 1118 name = "ccn"; arm_ccn_pmu_init() 1120 int len = snprintf(NULL, 0, "ccn_%d", ccn->dt.id); arm_ccn_pmu_init() 1122 name = devm_kzalloc(ccn->dev, len + 1, GFP_KERNEL); arm_ccn_pmu_init() 1123 snprintf(name, len + 1, "ccn_%d", ccn->dt.id); arm_ccn_pmu_init() 1127 ccn->dt.pmu = (struct pmu) { arm_ccn_pmu_init() 1139 if (!ccn->irq_used) { arm_ccn_pmu_init() 1140 dev_info(ccn->dev, "No access to interrupts, using timer.\n"); arm_ccn_pmu_init() 1141 hrtimer_init(&ccn->dt.hrtimer, CLOCK_MONOTONIC, arm_ccn_pmu_init() 1143 ccn->dt.hrtimer.function = arm_ccn_pmu_timer_handler; arm_ccn_pmu_init() 1146 return perf_pmu_register(&ccn->dt.pmu, name, -1); arm_ccn_pmu_init() 1149 static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn) arm_ccn_pmu_cleanup() argument 1153 for (i = 0; i < ccn->num_xps; i++) arm_ccn_pmu_cleanup() 1154 writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL); arm_ccn_pmu_cleanup() 1155 writel(0, ccn->dt.base + CCN_DT_PMCR); arm_ccn_pmu_cleanup() 1156 perf_pmu_unregister(&ccn->dt.pmu); arm_ccn_pmu_cleanup() 1157 ida_simple_remove(&arm_ccn_pmu_ida, ccn->dt.id); arm_ccn_pmu_cleanup() 1161 static int arm_ccn_for_each_valid_region(struct arm_ccn *ccn, arm_ccn_for_each_valid_region() argument 1162 int (*callback)(struct arm_ccn *ccn, int region, arm_ccn_for_each_valid_region() 1172 val = readl(ccn->base + CCN_MN_OLY_COMP_LIST_63_0 + arm_ccn_for_each_valid_region() 1177 base = ccn->base + region * CCN_REGION_SIZE; arm_ccn_for_each_valid_region() 1184 err = callback(ccn, region, base, type, id); arm_ccn_for_each_valid_region() 1192 static int arm_ccn_get_nodes_num(struct arm_ccn *ccn, int region, arm_ccn_get_nodes_num() argument 1196 if (type == CCN_TYPE_XP && id >= ccn->num_xps) arm_ccn_get_nodes_num() 1197 ccn->num_xps = id + 1; arm_ccn_get_nodes_num() 1198 else if (id >= ccn->num_nodes) arm_ccn_get_nodes_num() 1199 ccn->num_nodes = id + 1; arm_ccn_get_nodes_num() 1204 static int arm_ccn_init_nodes(struct arm_ccn *ccn, int region, arm_ccn_init_nodes() argument 1209 dev_dbg(ccn->dev, "Region %d: id=%u, type=0x%02x\n", region, id, type); arm_ccn_init_nodes() 1216 component = &ccn->xp[id]; arm_ccn_init_nodes() 1219 ccn->sbsx_present = 1; arm_ccn_init_nodes() 1220 component = &ccn->node[id]; arm_ccn_init_nodes() 1223 ccn->sbas_present = 1; arm_ccn_init_nodes() 1226 component = &ccn->node[id]; arm_ccn_init_nodes() 1237 static irqreturn_t arm_ccn_error_handler(struct arm_ccn *ccn, arm_ccn_error_handler() argument 1241 dev_err(ccn->dev, "Error reported in %08x%08x%08x%08x%08x%08x.\n", arm_ccn_error_handler() 1244 dev_err(ccn->dev, "Disabling interrupt generation for all errors.\n"); arm_ccn_error_handler() 1246 ccn->base + CCN_MN_ERRINT_STATUS); arm_ccn_error_handler() 1255 struct arm_ccn *ccn = dev_id; arm_ccn_irq_handler() local 1261 err_or = err_sig_val[0] = readl(ccn->base + CCN_MN_ERR_SIG_VAL_63_0); arm_ccn_irq_handler() 1264 res = arm_ccn_pmu_overflow_handler(&ccn->dt); arm_ccn_irq_handler() 1269 err_sig_val[i] = readl(ccn->base + arm_ccn_irq_handler() 1274 res |= arm_ccn_error_handler(ccn, err_sig_val); arm_ccn_irq_handler() 1278 ccn->base + CCN_MN_ERRINT_STATUS); arm_ccn_irq_handler() 1286 struct arm_ccn *ccn; arm_ccn_probe() local 1290 ccn = devm_kzalloc(&pdev->dev, sizeof(*ccn), GFP_KERNEL); arm_ccn_probe() 1291 if (!ccn) arm_ccn_probe() 1293 ccn->dev = &pdev->dev; arm_ccn_probe() 1294 platform_set_drvdata(pdev, ccn); arm_ccn_probe() 1300 if (!devm_request_mem_region(ccn->dev, res->start, arm_ccn_probe() 1304 ccn->base = devm_ioremap(ccn->dev, res->start, arm_ccn_probe() 1306 if (!ccn->base) arm_ccn_probe() 1315 ccn->base + CCN_MN_ERRINT_STATUS); arm_ccn_probe() 1316 if (readl(ccn->base + CCN_MN_ERRINT_STATUS) & arm_ccn_probe() 1320 ccn->base + CCN_MN_ERRINT_STATUS); arm_ccn_probe() 1321 err = devm_request_irq(ccn->dev, res->start, arm_ccn_probe() 1322 arm_ccn_irq_handler, 0, dev_name(ccn->dev), arm_ccn_probe() 1323 ccn); arm_ccn_probe() 1327 ccn->irq_used = 1; arm_ccn_probe() 1333 err = arm_ccn_for_each_valid_region(ccn, arm_ccn_get_nodes_num); arm_ccn_probe() 1337 ccn->node = devm_kzalloc(ccn->dev, sizeof(*ccn->node) * ccn->num_nodes, arm_ccn_probe() 1339 ccn->xp = devm_kzalloc(ccn->dev, sizeof(*ccn->node) * ccn->num_xps, arm_ccn_probe() 1341 if (!ccn->node || !ccn->xp) arm_ccn_probe() 1344 err = arm_ccn_for_each_valid_region(ccn, arm_ccn_init_nodes); arm_ccn_probe() 1348 return arm_ccn_pmu_init(ccn); arm_ccn_probe() 1353 struct arm_ccn *ccn = platform_get_drvdata(pdev); arm_ccn_remove() local 1355 arm_ccn_pmu_cleanup(ccn); arm_ccn_remove() 1361 { .compatible = "arm,ccn-504", }, 1367 .name = "arm-ccn",
|