Lines Matching +full:counter +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0
3 * ARMv6 Performance counter handling code.
7 * ARMv6 has 2 configurable performance counters and a single cycle counter.
16 * the event bus. The procedure for disabling a configurable counter is:
17 * - change the counter to count the ETMEXTOUT[0] signal (0x20). This
18 * effectively stops the counter from counting.
19 * - disable the counter's interrupt generation (each counter has it's
21 * Once stopped, the counter value can be written as 0 to reset.
23 * To enable a counter:
24 * - enable the counter's interrupt generation.
25 * - set the new event type.
27 * Note: the dedicated cycle counter only counts cycles and can't be
29 * cycle counter, we have to just disable the interrupt reporting and start
30 * ignoring that counter. When re-enabling, we have to reset the value and
107 * can use a raw counter.
130 #define ARMV6_PMCR_ENABLE (1 << 0)
131 #define ARMV6_PMCR_CTR01_RESET (1 << 1)
132 #define ARMV6_PMCR_CCOUNT_RESET (1 << 2)
133 #define ARMV6_PMCR_CCOUNT_DIV (1 << 3)
134 #define ARMV6_PMCR_COUNT0_IEN (1 << 4)
135 #define ARMV6_PMCR_COUNT1_IEN (1 << 5)
136 #define ARMV6_PMCR_CCOUNT_IEN (1 << 6)
137 #define ARMV6_PMCR_COUNT0_OVERFLOW (1 << 8)
138 #define ARMV6_PMCR_COUNT1_OVERFLOW (1 << 9)
139 #define ARMV6_PMCR_CCOUNT_OVERFLOW (1 << 10)
157 enum armv6_counters counter) in armv6_pmcr_counter_has_overflowed() argument
161 if (ARMV6_CYCLE_COUNTER == counter) in armv6_pmcr_counter_has_overflowed()
163 else if (ARMV6_COUNTER0 == counter) in armv6_pmcr_counter_has_overflowed()
165 else if (ARMV6_COUNTER1 == counter) in armv6_pmcr_counter_has_overflowed()
168 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6_pmcr_counter_has_overflowed()
175 struct hw_perf_event *hwc = &event->hw; in armv6pmu_read_counter()
176 int counter = hwc->idx; in armv6pmu_read_counter() local
179 if (ARMV6_CYCLE_COUNTER == counter) in armv6pmu_read_counter()
180 asm volatile("mrc p15, 0, %0, c15, c12, 1" : "=r"(value)); in armv6pmu_read_counter()
181 else if (ARMV6_COUNTER0 == counter) in armv6pmu_read_counter()
183 else if (ARMV6_COUNTER1 == counter) in armv6pmu_read_counter()
186 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6pmu_read_counter()
193 struct hw_perf_event *hwc = &event->hw; in armv6pmu_write_counter()
194 int counter = hwc->idx; in armv6pmu_write_counter() local
196 if (ARMV6_CYCLE_COUNTER == counter) in armv6pmu_write_counter()
197 asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r"(value)); in armv6pmu_write_counter()
198 else if (ARMV6_COUNTER0 == counter) in armv6pmu_write_counter()
200 else if (ARMV6_COUNTER1 == counter) in armv6pmu_write_counter()
203 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6pmu_write_counter()
209 struct hw_perf_event *hwc = &event->hw; in armv6pmu_enable_event()
210 int idx = hwc->idx; in armv6pmu_enable_event()
217 evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) | in armv6pmu_enable_event()
221 evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) | in armv6pmu_enable_event()
224 WARN_ONCE(1, "invalid counter number (%d)\n", idx); in armv6pmu_enable_event()
229 * Mask out the current event and set the counter to count the event in armv6pmu_enable_event()
243 struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); in armv6pmu_handle_irq()
259 for (idx = 0; idx < cpu_pmu->num_events; ++idx) { in armv6pmu_handle_irq()
260 struct perf_event *event = cpuc->events[idx]; in armv6pmu_handle_irq()
269 * each counter has overflowed before we process it. in armv6pmu_handle_irq()
274 hwc = &event->hw; in armv6pmu_handle_irq()
276 perf_sample_data_init(&data, 0, hwc->last_period); in armv6pmu_handle_irq()
281 cpu_pmu->disable(event); in armv6pmu_handle_irq()
318 struct hw_perf_event *hwc = &event->hw; in armv6pmu_get_event_idx()
319 /* Always place a cycle counter into the cycle counter. */ in armv6pmu_get_event_idx()
320 if (ARMV6_PERFCTR_CPU_CYCLES == hwc->config_base) { in armv6pmu_get_event_idx()
321 if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask)) in armv6pmu_get_event_idx()
322 return -EAGAIN; in armv6pmu_get_event_idx()
327 * For anything other than a cycle counter, try and use in armv6pmu_get_event_idx()
330 if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask)) in armv6pmu_get_event_idx()
333 if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask)) in armv6pmu_get_event_idx()
337 return -EAGAIN; in armv6pmu_get_event_idx()
344 clear_bit(event->hw.idx, cpuc->used_mask); in armv6pmu_clear_event_idx()
350 struct hw_perf_event *hwc = &event->hw; in armv6pmu_disable_event()
351 int idx = hwc->idx; in armv6pmu_disable_event()
363 WARN_ONCE(1, "invalid counter number (%d)\n", idx); in armv6pmu_disable_event()
368 * Mask out the current event and set the counter to count the number in armv6pmu_disable_event()
386 cpu_pmu->handle_irq = armv6pmu_handle_irq; in armv6pmu_init()
387 cpu_pmu->enable = armv6pmu_enable_event; in armv6pmu_init()
388 cpu_pmu->disable = armv6pmu_disable_event; in armv6pmu_init()
389 cpu_pmu->read_counter = armv6pmu_read_counter; in armv6pmu_init()
390 cpu_pmu->write_counter = armv6pmu_write_counter; in armv6pmu_init()
391 cpu_pmu->get_event_idx = armv6pmu_get_event_idx; in armv6pmu_init()
392 cpu_pmu->clear_event_idx = armv6pmu_clear_event_idx; in armv6pmu_init()
393 cpu_pmu->start = armv6pmu_start; in armv6pmu_init()
394 cpu_pmu->stop = armv6pmu_stop; in armv6pmu_init()
395 cpu_pmu->map_event = armv6_map_event; in armv6pmu_init()
396 cpu_pmu->num_events = 3; in armv6pmu_init()
402 cpu_pmu->name = "armv6_1136"; in armv6_1136_pmu_init()
409 cpu_pmu->name = "armv6_1156"; in armv6_1156_pmu_init()
416 cpu_pmu->name = "armv6_1176"; in armv6_1176_pmu_init()
421 {.compatible = "arm,arm1176-pmu", .data = armv6_1176_pmu_init},
422 {.compatible = "arm,arm1136-pmu", .data = armv6_1136_pmu_init},
441 .name = "armv6-pmu",