blob: fb78c10fd987458f7bcdb99cacc55b3e3ab0e22c [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/**
Jon Medhurst15ce78d2014-04-10 09:02:02 +01002 * Copyright (C) ARM Limited 2013-2014. All rights reserved.
Jon Medhurstaaf37a32013-06-11 12:10:56 +01003 *
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
Jon Medhurstd3698592013-10-10 16:48:56 +010017static bool map_cpuids;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010018static int mpidr_cpuids[NR_CPUS];
Jon Medhurst96b56152014-10-30 18:01:15 +000019static const struct gator_cpu *mpidr_cpus[NR_CPUS];
Jon Medhurstaaf37a32013-06-11 12:10:56 +010020static int __lcpu_to_pcpu[NR_CPUS];
21
Jon Medhurstd3698592013-10-10 16:48:56 +010022static const struct gator_cpu *gator_find_cpu_by_dt_name(const char *const name)
23{
24 int i;
25
26 for (i = 0; gator_cpus[i].cpuid != 0; ++i) {
27 const struct gator_cpu *const gator_cpu = &gator_cpus[i];
Jon Medhurst96b56152014-10-30 18:01:15 +000028
29 if (gator_cpu->dt_name != NULL && strcmp(gator_cpu->dt_name, name) == 0)
Jon Medhurstd3698592013-10-10 16:48:56 +010030 return gator_cpu;
Jon Medhurstd3698592013-10-10 16:48:56 +010031 }
32
33 return NULL;
34}
35
Jon Medhurstaaf37a32013-06-11 12:10:56 +010036static void calc_first_cluster_size(void)
37{
38 int len;
39 const u32 *val;
Jon Medhurstd3698592013-10-10 16:48:56 +010040 const char *compatible;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010041 struct device_node *cn = NULL;
42 int mpidr_cpuids_count = 0;
43
Jon Medhurst96b56152014-10-30 18:01:15 +000044 /* Zero is a valid cpuid, so initialize the array to 0xff's */
Jon Medhurstaaf37a32013-06-11 12:10:56 +010045 memset(&mpidr_cpuids, 0xff, sizeof(mpidr_cpuids));
Jon Medhurstd3698592013-10-10 16:48:56 +010046 memset(&mpidr_cpus, 0, sizeof(mpidr_cpus));
Jon Medhurstaaf37a32013-06-11 12:10:56 +010047
48 while ((cn = of_find_node_by_type(cn, "cpu"))) {
49 BUG_ON(mpidr_cpuids_count >= NR_CPUS);
50
51 val = of_get_property(cn, "reg", &len);
52 if (!val || len != 4) {
53 pr_err("%s missing reg property\n", cn->full_name);
54 continue;
55 }
Jon Medhurstd3698592013-10-10 16:48:56 +010056 compatible = of_get_property(cn, "compatible", NULL);
57 if (compatible == NULL) {
58 pr_err("%s missing compatible property\n", cn->full_name);
59 continue;
60 }
Jon Medhurstaaf37a32013-06-11 12:10:56 +010061
62 mpidr_cpuids[mpidr_cpuids_count] = be32_to_cpup(val);
Jon Medhurstd3698592013-10-10 16:48:56 +010063 mpidr_cpus[mpidr_cpuids_count] = gator_find_cpu_by_dt_name(compatible);
Jon Medhurstaaf37a32013-06-11 12:10:56 +010064 ++mpidr_cpuids_count;
65 }
66
Jon Medhurstd3698592013-10-10 16:48:56 +010067 map_cpuids = (mpidr_cpuids_count == nr_cpu_ids);
Jon Medhurstaaf37a32013-06-11 12:10:56 +010068}
69
70static int linearize_mpidr(int mpidr)
71{
72 int i;
Jon Medhurst96b56152014-10-30 18:01:15 +000073
Jon Medhurstaaf37a32013-06-11 12:10:56 +010074 for (i = 0; i < nr_cpu_ids; ++i) {
Jon Medhurst96b56152014-10-30 18:01:15 +000075 if (mpidr_cpuids[i] == mpidr)
Jon Medhurstaaf37a32013-06-11 12:10:56 +010076 return i;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010077 }
78
79 BUG();
80}
81
82int lcpu_to_pcpu(const int lcpu)
83{
84 int pcpu;
Jon Medhurstd3698592013-10-10 16:48:56 +010085
86 if (!map_cpuids)
87 return lcpu;
88
Jon Medhurstaaf37a32013-06-11 12:10:56 +010089 BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0);
90 pcpu = __lcpu_to_pcpu[lcpu];
91 BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0);
92 return pcpu;
93}
94
95int pcpu_to_lcpu(const int pcpu)
96{
97 int lcpu;
Jon Medhurstd3698592013-10-10 16:48:56 +010098
99 if (!map_cpuids)
100 return pcpu;
101
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100102 BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0);
103 for (lcpu = 0; lcpu < nr_cpu_ids; ++lcpu) {
104 if (__lcpu_to_pcpu[lcpu] == pcpu) {
105 BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0);
106 return lcpu;
107 }
108 }
109 BUG();
110}
111
112static void gator_update_cpu_mapping(u32 cpu_hwid)
113{
114 int lcpu = smp_processor_id();
115 int pcpu = linearize_mpidr(cpu_hwid & MPIDR_HWID_BITMASK);
Jon Medhurst96b56152014-10-30 18:01:15 +0000116
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100117 BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0);
118 BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0);
119 __lcpu_to_pcpu[lcpu] = pcpu;
120}
121
122GATOR_DEFINE_PROBE(cpu_migrate_begin, TP_PROTO(u64 timestamp, u32 cpu_hwid))
123{
124 const int cpu = get_physical_cpu();
125
126 gator_timer_offline((void *)1);
127 gator_timer_offline_dispatch(cpu, true);
128}
129
130GATOR_DEFINE_PROBE(cpu_migrate_finish, TP_PROTO(u64 timestamp, u32 cpu_hwid))
131{
132 int cpu;
133
134 gator_update_cpu_mapping(cpu_hwid);
135
Jon Medhurst96b56152014-10-30 18:01:15 +0000136 /* get_physical_cpu must be called after gator_update_cpu_mapping */
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100137 cpu = get_physical_cpu();
138 gator_timer_online_dispatch(cpu, true);
139 gator_timer_online((void *)1);
140}
141
142GATOR_DEFINE_PROBE(cpu_migrate_current, TP_PROTO(u64 timestamp, u32 cpu_hwid))
143{
144 gator_update_cpu_mapping(cpu_hwid);
145}
146
Jon Medhurstd3698592013-10-10 16:48:56 +0100147static void gator_send_iks_core_names(void)
148{
149 int cpu;
Jon Medhurst96b56152014-10-30 18:01:15 +0000150 /* Send the cpu names */
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100151 preempt_disable();
Jon Medhurstd3698592013-10-10 16:48:56 +0100152 for (cpu = 0; cpu < nr_cpu_ids; ++cpu) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000153 if (mpidr_cpus[cpu] != NULL)
Jon Medhurste31266f2014-08-04 15:47:44 +0100154 gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid);
Jon Medhurstd3698592013-10-10 16:48:56 +0100155 }
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100156 preempt_enable();
Jon Medhurstd3698592013-10-10 16:48:56 +0100157}
158
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100159static int gator_migrate_start(void)
160{
161 int retval = 0;
Jon Medhurstd3698592013-10-10 16:48:56 +0100162
163 if (!map_cpuids)
164 return retval;
165
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100166 if (retval == 0)
167 retval = GATOR_REGISTER_TRACE(cpu_migrate_begin);
168 if (retval == 0)
169 retval = GATOR_REGISTER_TRACE(cpu_migrate_finish);
170 if (retval == 0)
171 retval = GATOR_REGISTER_TRACE(cpu_migrate_current);
172 if (retval == 0) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000173 /* Initialize the logical to physical cpu mapping */
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100174 memset(&__lcpu_to_pcpu, 0xff, sizeof(__lcpu_to_pcpu));
175 bL_switcher_trace_trigger();
176 }
177 return retval;
178}
179
180static void gator_migrate_stop(void)
181{
Jon Medhurstd3698592013-10-10 16:48:56 +0100182 if (!map_cpuids)
183 return;
184
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100185 GATOR_UNREGISTER_TRACE(cpu_migrate_current);
186 GATOR_UNREGISTER_TRACE(cpu_migrate_finish);
187 GATOR_UNREGISTER_TRACE(cpu_migrate_begin);
188}
189
190#else
191
192#define calc_first_cluster_size()
Jon Medhurstd3698592013-10-10 16:48:56 +0100193#define gator_send_iks_core_names()
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100194#define gator_migrate_start() 0
195#define gator_migrate_stop()
196
197#endif