1f22e705eSMichal Mazurek /* SPDX-License-Identifier: BSD-3-Clause
2f22e705eSMichal Mazurek * Copyright(c) 2015 Cavium, Inc
3f22e705eSMichal Mazurek * Copyright(c) 2022 StarFive
4f22e705eSMichal Mazurek * Copyright(c) 2022 SiFive
5f22e705eSMichal Mazurek * Copyright(c) 2022 Semihalf
6f22e705eSMichal Mazurek */
7f22e705eSMichal Mazurek
8f22e705eSMichal Mazurek #include <stdio.h>
9f22e705eSMichal Mazurek
10f22e705eSMichal Mazurek #include "eal_private.h"
11f22e705eSMichal Mazurek #include "rte_byteorder.h"
12f22e705eSMichal Mazurek #include "rte_cycles.h"
13f22e705eSMichal Mazurek #include "rte_log.h"
14f22e705eSMichal Mazurek
15f22e705eSMichal Mazurek /** Read generic counter frequency */
16f22e705eSMichal Mazurek static uint64_t
__rte_riscv_timefrq(void)17f22e705eSMichal Mazurek __rte_riscv_timefrq(void)
18f22e705eSMichal Mazurek {
19f22e705eSMichal Mazurek #define TIMEBASE_FREQ_SIZE 8
20f22e705eSMichal Mazurek if (RTE_RISCV_TIME_FREQ > 0)
21f22e705eSMichal Mazurek return RTE_RISCV_TIME_FREQ;
22f22e705eSMichal Mazurek uint8_t buf[TIMEBASE_FREQ_SIZE];
23f22e705eSMichal Mazurek ssize_t cnt;
24f22e705eSMichal Mazurek FILE *file;
25f22e705eSMichal Mazurek
26f22e705eSMichal Mazurek file = fopen("/proc/device-tree/cpus/timebase-frequency", "rb");
27f22e705eSMichal Mazurek if (!file)
28f22e705eSMichal Mazurek goto fail;
29f22e705eSMichal Mazurek
30f22e705eSMichal Mazurek cnt = fread(buf, 1, TIMEBASE_FREQ_SIZE, file);
31f22e705eSMichal Mazurek fclose(file);
32f22e705eSMichal Mazurek switch (cnt) {
33f22e705eSMichal Mazurek case 8:
34f22e705eSMichal Mazurek return rte_be_to_cpu_64(*(uint64_t *)buf);
35f22e705eSMichal Mazurek case 4:
36f22e705eSMichal Mazurek return rte_be_to_cpu_32(*(uint32_t *)buf);
37f22e705eSMichal Mazurek default:
38f22e705eSMichal Mazurek break;
39f22e705eSMichal Mazurek }
40f22e705eSMichal Mazurek fail:
41*ae67895bSDavid Marchand EAL_LOG(WARNING, "Unable to read timebase-frequency from FDT.");
42f22e705eSMichal Mazurek return 0;
43f22e705eSMichal Mazurek }
44f22e705eSMichal Mazurek
45f22e705eSMichal Mazurek uint64_t
get_tsc_freq_arch(void)46f22e705eSMichal Mazurek get_tsc_freq_arch(void)
47f22e705eSMichal Mazurek {
48*ae67895bSDavid Marchand EAL_LOG(NOTICE, "TSC using RISC-V %s.",
49f22e705eSMichal Mazurek RTE_RISCV_RDTSC_USE_HPM ? "rdcycle" : "rdtime");
50f22e705eSMichal Mazurek if (!RTE_RISCV_RDTSC_USE_HPM)
51f22e705eSMichal Mazurek return __rte_riscv_timefrq();
52f22e705eSMichal Mazurek #define CYC_PER_1MHZ 1E6
53f22e705eSMichal Mazurek /*
54f22e705eSMichal Mazurek * Use real time clock to estimate current cycle frequency
55f22e705eSMichal Mazurek */
56f22e705eSMichal Mazurek uint64_t ticks, frq;
57f22e705eSMichal Mazurek uint64_t start_ticks, cur_ticks;
58f22e705eSMichal Mazurek uint64_t start_cycle, end_cycle;
59f22e705eSMichal Mazurek
60f22e705eSMichal Mazurek /* Do not proceed unless clock frequency can be obtained. */
61f22e705eSMichal Mazurek frq = __rte_riscv_timefrq();
62f22e705eSMichal Mazurek if (!frq)
63f22e705eSMichal Mazurek return 0;
64f22e705eSMichal Mazurek
65f22e705eSMichal Mazurek /* Number of ticks for 1/10 second */
66f22e705eSMichal Mazurek ticks = frq / 10;
67f22e705eSMichal Mazurek
68f22e705eSMichal Mazurek start_ticks = __rte_riscv_rdtime_precise();
69f22e705eSMichal Mazurek start_cycle = rte_rdtsc_precise();
70f22e705eSMichal Mazurek do {
71f22e705eSMichal Mazurek cur_ticks = __rte_riscv_rdtime();
72f22e705eSMichal Mazurek } while ((cur_ticks - start_ticks) < ticks);
73f22e705eSMichal Mazurek end_cycle = rte_rdtsc_precise();
74f22e705eSMichal Mazurek
75f22e705eSMichal Mazurek /* Adjust the cycles to next 1Mhz */
76f22e705eSMichal Mazurek return RTE_ALIGN_MUL_CEIL((end_cycle - start_cycle) * 10, CYC_PER_1MHZ);
77f22e705eSMichal Mazurek }
78