Lines Matching +full:interrupt +full:- +full:counter

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
20 * own interrupt enable bit).
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
31 * enable the interrupt.
106 * can use a raw counter.
156 enum armv6_counters counter) in armv6_pmcr_counter_has_overflowed() argument
160 if (ARMV6_CYCLE_COUNTER == counter) in armv6_pmcr_counter_has_overflowed()
162 else if (ARMV6_COUNTER0 == counter) in armv6_pmcr_counter_has_overflowed()
164 else if (ARMV6_COUNTER1 == counter) in armv6_pmcr_counter_has_overflowed()
167 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6_pmcr_counter_has_overflowed()
174 struct hw_perf_event *hwc = &event->hw; in armv6pmu_read_counter()
175 int counter = hwc->idx; in armv6pmu_read_counter() local
178 if (ARMV6_CYCLE_COUNTER == counter) in armv6pmu_read_counter()
180 else if (ARMV6_COUNTER0 == counter) in armv6pmu_read_counter()
182 else if (ARMV6_COUNTER1 == counter) in armv6pmu_read_counter()
185 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6pmu_read_counter()
192 struct hw_perf_event *hwc = &event->hw; in armv6pmu_write_counter()
193 int counter = hwc->idx; in armv6pmu_write_counter() local
195 if (ARMV6_CYCLE_COUNTER == counter) in armv6pmu_write_counter()
197 else if (ARMV6_COUNTER0 == counter) in armv6pmu_write_counter()
199 else if (ARMV6_COUNTER1 == counter) in armv6pmu_write_counter()
202 WARN_ONCE(1, "invalid counter number (%d)\n", counter); in armv6pmu_write_counter()
208 struct hw_perf_event *hwc = &event->hw; in armv6pmu_enable_event()
209 int idx = hwc->idx; in armv6pmu_enable_event()
216 evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) | in armv6pmu_enable_event()
220 evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) | in armv6pmu_enable_event()
223 WARN_ONCE(1, "invalid counter number (%d)\n", idx); in armv6pmu_enable_event()
228 * Mask out the current event and set the counter to count the event in armv6pmu_enable_event()
242 struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); in armv6pmu_handle_irq()
258 for_each_set_bit(idx, cpu_pmu->cntr_mask, ARMV6_NUM_COUNTERS) { in armv6pmu_handle_irq()
259 struct perf_event *event = cpuc->events[idx]; in armv6pmu_handle_irq()
267 * We have a single interrupt for all counters. Check that in armv6pmu_handle_irq()
268 * each counter has overflowed before we process it. in armv6pmu_handle_irq()
273 hwc = &event->hw; in armv6pmu_handle_irq()
275 perf_sample_data_init(&data, 0, hwc->last_period); in armv6pmu_handle_irq()
280 cpu_pmu->disable(event); in armv6pmu_handle_irq()
317 struct hw_perf_event *hwc = &event->hw; in armv6pmu_get_event_idx()
318 /* Always place a cycle counter into the cycle counter. */ in armv6pmu_get_event_idx()
319 if (ARMV6_PERFCTR_CPU_CYCLES == hwc->config_base) { in armv6pmu_get_event_idx()
320 if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask)) in armv6pmu_get_event_idx()
321 return -EAGAIN; in armv6pmu_get_event_idx()
326 * For anything other than a cycle counter, try and use in armv6pmu_get_event_idx()
329 if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask)) in armv6pmu_get_event_idx()
332 if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask)) in armv6pmu_get_event_idx()
336 return -EAGAIN; in armv6pmu_get_event_idx()
343 clear_bit(event->hw.idx, cpuc->used_mask); in armv6pmu_clear_event_idx()
349 struct hw_perf_event *hwc = &event->hw; in armv6pmu_disable_event()
350 int idx = hwc->idx; in armv6pmu_disable_event()
362 WARN_ONCE(1, "invalid counter number (%d)\n", idx); in armv6pmu_disable_event()
367 * Mask out the current event and set the counter to count the number in armv6pmu_disable_event()
385 cpu_pmu->handle_irq = armv6pmu_handle_irq; in armv6pmu_init()
386 cpu_pmu->enable = armv6pmu_enable_event; in armv6pmu_init()
387 cpu_pmu->disable = armv6pmu_disable_event; in armv6pmu_init()
388 cpu_pmu->read_counter = armv6pmu_read_counter; in armv6pmu_init()
389 cpu_pmu->write_counter = armv6pmu_write_counter; in armv6pmu_init()
390 cpu_pmu->get_event_idx = armv6pmu_get_event_idx; in armv6pmu_init()
391 cpu_pmu->clear_event_idx = armv6pmu_clear_event_idx; in armv6pmu_init()
392 cpu_pmu->start = armv6pmu_start; in armv6pmu_init()
393 cpu_pmu->stop = armv6pmu_stop; in armv6pmu_init()
394 cpu_pmu->map_event = armv6_map_event; in armv6pmu_init()
396 bitmap_set(cpu_pmu->cntr_mask, 0, ARMV6_NUM_COUNTERS); in armv6pmu_init()
402 cpu_pmu->name = "armv6_1136"; in armv6_1136_pmu_init()
409 cpu_pmu->name = "armv6_1176"; in armv6_1176_pmu_init()
414 {.compatible = "arm,arm1176-pmu", .data = armv6_1176_pmu_init},
415 {.compatible = "arm,arm1136-pmu", .data = armv6_1136_pmu_init},
426 .name = "armv6-pmu",