firmware/br-ext-chip-allwinner/board/v83x/kernel/patches/00000-drivers_cpuidle_cpuid...

119 lines
3.7 KiB
Diff

diff -drupN a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
--- a/drivers/cpuidle/cpuidle.c 2018-08-06 17:23:04.000000000 +0300
+++ b/drivers/cpuidle/cpuidle.c 2022-06-12 05:28:14.000000000 +0300
@@ -160,6 +160,60 @@ int cpuidle_enter_freeze(struct cpuidle_
}
#endif /* CONFIG_SUSPEND */
+#ifdef CONFIG_ARM_SUNXI_CPUIDLE_TIMESTAMP
+static inline u64 arch_counter_get_cntpct(void)
+{
+ u64 cval;
+
+ isb();
+ asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
+ return cval;
+}
+
+/*
+ * 0xc0020800~0xc0021000 is reserved in dts,
+ * just follow standby space.
+ * this space is used to record the timestamps
+ * of each stage in cpuidle. each cpu occupy
+ * 48 bytes.
+ */
+#define CPUIDLE_TIMESTAMPS_BASE (phys_to_virt((const volatile void *)0x40020800))
+#define DIV24(x) (((x) * 85) >> 11)
+
+typedef struct cpuidle_timestamps {
+ /* Linux record when cpuidle enter */
+ u64 cpux_idle_enter_time;
+ /* optee record before wfi */
+ u64 cpux_idle_finish_time;
+ /* cpus record when core down */
+ u64 cpux_core_down_time;
+ /* cpus record when gicout */
+ u64 cpus_wake_up_time;
+ /* optee record when core up */
+ u64 cpux_start_wake_time;
+ /* Linux record when cpuidle exit */
+ u64 cpux_wakeup_finish_time;
+} cpuidle_timestamps_t;
+
+#define software_core_close_time(cpu) \
+ (cpuidle_time[cpu].cpux_idle_finish_time -\
+ cpuidle_time[cpu].cpux_idle_enter_time)
+#define hardware_core_close_time(cpu) \
+ (cpuidle_time[cpu].cpux_core_down_time -\
+ cpuidle_time[cpu].cpux_idle_finish_time)
+
+#define software_core_open_time(cpu) \
+ (cpuidle_time[cpu].cpux_wakeup_finish_time -\
+ cpuidle_time[cpu].cpux_start_wake_time)
+#define hardware_core_open_time(cpu) \
+ (cpuidle_time[cpu].cpux_start_wake_time -\
+ cpuidle_time[cpu].cpus_wake_up_time)
+
+#define resident_core_down_time(cpu) \
+ (cpuidle_time[cpu].cpux_wakeup_finish_time -\
+ cpuidle_time[cpu].cpux_idle_enter_time)
+
+#endif
/**
* cpuidle_enter_state - enter the state and update stats
* @dev: cpuidle device for this cpu
@@ -175,7 +229,11 @@ int cpuidle_enter_state(struct cpuidle_d
bool broadcast = !!(target_state->flags & CPUIDLE_FLAG_TIMER_STOP);
ktime_t time_start, time_end;
s64 diff;
-
+#ifdef CONFIG_ARM_SUNXI_CPUIDLE_TIMESTAMP
+ int cpu = smp_processor_id();
+ cpuidle_timestamps_t *cpuidle_time =
+ (cpuidle_timestamps_t *)CPUIDLE_TIMESTAMPS_BASE;
+#endif
/*
* Tell the time framework to switch to a broadcast timer because our
* local timer will be shut down. If a local timer is used from another
@@ -193,20 +251,37 @@ int cpuidle_enter_state(struct cpuidle_d
}
/* Take note of the planned idle state. */
- sched_idle_set_state(target_state);
+ sched_idle_set_state(target_state, index);
trace_cpu_idle_rcuidle(index, dev->cpu);
time_start = ns_to_ktime(local_clock());
-
stop_critical_timings();
+
+#ifdef CONFIG_ARM_SUNXI_CPUIDLE_TIMESTAMP
+ if ((index > 0) && (cpu != 0))
+ cpuidle_time[cpu].cpux_idle_enter_time =
+ arch_counter_get_cntpct();
+#endif
entered_state = target_state->enter(dev, drv, index);
+#ifdef CONFIG_ARM_SUNXI_CPUIDLE_TIMESTAMP
+ if ((index > 0) && (cpu != 0) && (cpu == smp_processor_id())) {
+ cpuidle_time[cpu].cpux_wakeup_finish_time =
+ arch_counter_get_cntpct();
+ pr_err("c%d, es:%lld, eh:%lld, xh:%lld, xs:%lld, r:%lld\n", cpu,
+ DIV24(software_core_close_time(cpu)),
+ DIV24(hardware_core_close_time(cpu)),
+ DIV24(hardware_core_open_time(cpu)),
+ DIV24(software_core_open_time(cpu)),
+ DIV24(resident_core_down_time(cpu)));
+ }
+#endif
start_critical_timings();
time_end = ns_to_ktime(local_clock());
trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
/* The cpu is no longer idle or about to enter idle. */
- sched_idle_set_state(NULL);
+ sched_idle_set_state(NULL, -1);
if (broadcast) {
if (WARN_ON_ONCE(!irqs_disabled()))