2 * Copyright (C) ARM Limited 2013. All rights reserved.
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.
13 #include <asm/bL_switcher.h>
14 #include <asm/smp_plat.h>
15 #include <trace/events/power_cpu_migrate.h>
17 static bool map_cpuids;
18 static int mpidr_cpuids[NR_CPUS];
19 static const struct gator_cpu * mpidr_cpus[NR_CPUS];
20 static int __lcpu_to_pcpu[NR_CPUS];
22 static const struct gator_cpu *gator_find_cpu_by_dt_name(const char *const name)
26 for (i = 0; gator_cpus[i].cpuid != 0; ++i) {
27 const struct gator_cpu *const gator_cpu = &gator_cpus[i];
28 if (gator_cpu->dt_name != NULL && strcmp(gator_cpu->dt_name, name) == 0) {
36 static void calc_first_cluster_size(void)
40 const char *compatible;
41 struct device_node *cn = NULL;
42 int mpidr_cpuids_count = 0;
44 // Zero is a valid cpuid, so initialize the array to 0xff's
45 memset(&mpidr_cpuids, 0xff, sizeof(mpidr_cpuids));
46 memset(&mpidr_cpus, 0, sizeof(mpidr_cpus));
48 while ((cn = of_find_node_by_type(cn, "cpu"))) {
49 BUG_ON(mpidr_cpuids_count >= NR_CPUS);
51 val = of_get_property(cn, "reg", &len);
52 if (!val || len != 4) {
53 pr_err("%s missing reg property\n", cn->full_name);
56 compatible = of_get_property(cn, "compatible", NULL);
57 if (compatible == NULL) {
58 pr_err("%s missing compatible property\n", cn->full_name);
62 mpidr_cpuids[mpidr_cpuids_count] = be32_to_cpup(val);
63 mpidr_cpus[mpidr_cpuids_count] = gator_find_cpu_by_dt_name(compatible);
67 map_cpuids = (mpidr_cpuids_count == nr_cpu_ids);
70 static int linearize_mpidr(int mpidr)
73 for (i = 0; i < nr_cpu_ids; ++i) {
74 if (mpidr_cpuids[i] == mpidr) {
82 int lcpu_to_pcpu(const int lcpu)
89 BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0);
90 pcpu = __lcpu_to_pcpu[lcpu];
91 BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0);
95 int pcpu_to_lcpu(const int pcpu)
102 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);
112 static void gator_update_cpu_mapping(u32 cpu_hwid)
114 int lcpu = smp_processor_id();
115 int pcpu = linearize_mpidr(cpu_hwid & MPIDR_HWID_BITMASK);
116 BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0);
117 BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0);
118 __lcpu_to_pcpu[lcpu] = pcpu;
121 GATOR_DEFINE_PROBE(cpu_migrate_begin, TP_PROTO(u64 timestamp, u32 cpu_hwid))
123 const int cpu = get_physical_cpu();
125 gator_timer_offline((void *)1);
126 gator_timer_offline_dispatch(cpu, true);
129 GATOR_DEFINE_PROBE(cpu_migrate_finish, TP_PROTO(u64 timestamp, u32 cpu_hwid))
133 gator_update_cpu_mapping(cpu_hwid);
135 // get_physical_cpu must be called after gator_update_cpu_mapping
136 cpu = get_physical_cpu();
137 gator_timer_online_dispatch(cpu, true);
138 gator_timer_online((void *)1);
141 GATOR_DEFINE_PROBE(cpu_migrate_current, TP_PROTO(u64 timestamp, u32 cpu_hwid))
143 gator_update_cpu_mapping(cpu_hwid);
146 static void gator_send_iks_core_names(void)
149 // Send the cpu names
151 for (cpu = 0; cpu < nr_cpu_ids; ++cpu) {
152 if (mpidr_cpus[cpu] != NULL) {
153 gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid, mpidr_cpus[cpu]);
159 static int gator_migrate_start(void)
167 retval = GATOR_REGISTER_TRACE(cpu_migrate_begin);
169 retval = GATOR_REGISTER_TRACE(cpu_migrate_finish);
171 retval = GATOR_REGISTER_TRACE(cpu_migrate_current);
173 // Initialize the logical to physical cpu mapping
174 memset(&__lcpu_to_pcpu, 0xff, sizeof(__lcpu_to_pcpu));
175 bL_switcher_trace_trigger();
180 static void gator_migrate_stop(void)
185 GATOR_UNREGISTER_TRACE(cpu_migrate_current);
186 GATOR_UNREGISTER_TRACE(cpu_migrate_finish);
187 GATOR_UNREGISTER_TRACE(cpu_migrate_begin);
192 #define calc_first_cluster_size()
193 #define gator_send_iks_core_names()
194 #define gator_migrate_start() 0
195 #define gator_migrate_stop()