blob: 932be26bfcf7f57d7995a289a85aa27c398b52d8 [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/**
2 * Copyright (C) ARM Limited 2013. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
9
10#if GATOR_IKS_SUPPORT
11
12#include <linux/of.h>
13#include <asm/bL_switcher.h>
14#include <asm/smp_plat.h>
15#include <trace/events/power_cpu_migrate.h>
16
17static int mpidr_cpuids[NR_CPUS];
18static int __lcpu_to_pcpu[NR_CPUS];
19
20static void calc_first_cluster_size(void)
21{
22 int len;
23 const u32 *val;
24 struct device_node *cn = NULL;
25 int mpidr_cpuids_count = 0;
26
27 // Zero is a valid cpuid, so initialize the array to 0xff's
28 memset(&mpidr_cpuids, 0xff, sizeof(mpidr_cpuids));
29
30 while ((cn = of_find_node_by_type(cn, "cpu"))) {
31 BUG_ON(mpidr_cpuids_count >= NR_CPUS);
32
33 val = of_get_property(cn, "reg", &len);
34 if (!val || len != 4) {
35 pr_err("%s missing reg property\n", cn->full_name);
36 continue;
37 }
38
39 mpidr_cpuids[mpidr_cpuids_count] = be32_to_cpup(val);
40 ++mpidr_cpuids_count;
41 }
42
43 BUG_ON(mpidr_cpuids_count != nr_cpu_ids);
44}
45
46static int linearize_mpidr(int mpidr)
47{
48 int i;
49 for (i = 0; i < nr_cpu_ids; ++i) {
50 if (mpidr_cpuids[i] == mpidr) {
51 return i;
52 }
53 }
54
55 BUG();
56}
57
58int lcpu_to_pcpu(const int lcpu)
59{
60 int pcpu;
61 BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0);
62 pcpu = __lcpu_to_pcpu[lcpu];
63 BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0);
64 return pcpu;
65}
66
67int pcpu_to_lcpu(const int pcpu)
68{
69 int lcpu;
70 BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0);
71 for (lcpu = 0; lcpu < nr_cpu_ids; ++lcpu) {
72 if (__lcpu_to_pcpu[lcpu] == pcpu) {
73 BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0);
74 return lcpu;
75 }
76 }
77 BUG();
78}
79
80static void gator_update_cpu_mapping(u32 cpu_hwid)
81{
82 int lcpu = smp_processor_id();
83 int pcpu = linearize_mpidr(cpu_hwid & MPIDR_HWID_BITMASK);
84 BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0);
85 BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0);
86 __lcpu_to_pcpu[lcpu] = pcpu;
87}
88
89GATOR_DEFINE_PROBE(cpu_migrate_begin, TP_PROTO(u64 timestamp, u32 cpu_hwid))
90{
91 const int cpu = get_physical_cpu();
92
93 gator_timer_offline((void *)1);
94 gator_timer_offline_dispatch(cpu, true);
95}
96
97GATOR_DEFINE_PROBE(cpu_migrate_finish, TP_PROTO(u64 timestamp, u32 cpu_hwid))
98{
99 int cpu;
100
101 gator_update_cpu_mapping(cpu_hwid);
102
103 // get_physical_cpu must be called after gator_update_cpu_mapping
104 cpu = get_physical_cpu();
105 gator_timer_online_dispatch(cpu, true);
106 gator_timer_online((void *)1);
107}
108
109GATOR_DEFINE_PROBE(cpu_migrate_current, TP_PROTO(u64 timestamp, u32 cpu_hwid))
110{
111 gator_update_cpu_mapping(cpu_hwid);
112}
113
114static int gator_migrate_start(void)
115{
116 int retval = 0;
117 if (retval == 0)
118 retval = GATOR_REGISTER_TRACE(cpu_migrate_begin);
119 if (retval == 0)
120 retval = GATOR_REGISTER_TRACE(cpu_migrate_finish);
121 if (retval == 0)
122 retval = GATOR_REGISTER_TRACE(cpu_migrate_current);
123 if (retval == 0) {
124 // Initialize the logical to physical cpu mapping
125 memset(&__lcpu_to_pcpu, 0xff, sizeof(__lcpu_to_pcpu));
126 bL_switcher_trace_trigger();
127 }
128 return retval;
129}
130
131static void gator_migrate_stop(void)
132{
133 GATOR_UNREGISTER_TRACE(cpu_migrate_current);
134 GATOR_UNREGISTER_TRACE(cpu_migrate_finish);
135 GATOR_UNREGISTER_TRACE(cpu_migrate_begin);
136}
137
138#else
139
140#define calc_first_cluster_size()
141#define gator_migrate_start() 0
142#define gator_migrate_stop()
143
144#endif