summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/mips-cm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/mips-cm.c')
-rw-r--r--arch/mips/kernel/mips-cm.c55
1 files changed, 54 insertions, 1 deletions
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 3a115fab5573..43cb1e20baed 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -5,6 +5,7 @@
*/
#include <linux/errno.h>
+#include <linux/of.h>
#include <linux/percpu.h>
#include <linux/spinlock.h>
@@ -14,6 +15,7 @@
void __iomem *mips_gcr_base;
void __iomem *mips_cm_l2sync_base;
int mips_cm_is64;
+bool mips_cm_is_l2_hci_broken;
static char *cm2_tr[8] = {
"mem", "gcr", "gic", "mmio",
@@ -237,6 +239,18 @@ static void mips_cm_probe_l2sync(void)
mips_cm_l2sync_base = ioremap(addr, MIPS_CM_L2SYNC_SIZE);
}
+void mips_cm_update_property(void)
+{
+ struct device_node *cm_node;
+
+ cm_node = of_find_compatible_node(of_root, NULL, "mobileye,eyeq6-cm");
+ if (!cm_node)
+ return;
+ pr_info("HCI (Hardware Cache Init for the L2 cache) in GCR_L2_RAM_CONFIG from the CM3 is broken");
+ mips_cm_is_l2_hci_broken = true;
+ of_node_put(cm_node);
+}
+
int mips_cm_probe(void)
{
phys_addr_t addr;
@@ -308,7 +322,9 @@ void mips_cm_lock_other(unsigned int cluster, unsigned int core,
FIELD_PREP(CM3_GCR_Cx_OTHER_VP, vp);
if (cm_rev >= CM_REV_CM3_5) {
- val |= CM_GCR_Cx_OTHER_CLUSTER_EN;
+ if (cluster != cpu_cluster(&current_cpu_data))
+ val |= CM_GCR_Cx_OTHER_CLUSTER_EN;
+ val |= CM_GCR_Cx_OTHER_GIC_EN;
val |= FIELD_PREP(CM_GCR_Cx_OTHER_CLUSTER, cluster);
val |= FIELD_PREP(CM_GCR_Cx_OTHER_BLOCK, block);
} else {
@@ -512,3 +528,40 @@ void mips_cm_error_report(void)
/* reprime cause register */
write_gcr_error_cause(cm_error);
}
+
+unsigned int mips_cps_first_online_in_cluster(void)
+{
+ unsigned int local_cl;
+ int i;
+
+ local_cl = cpu_cluster(&current_cpu_data);
+
+ /*
+ * We rely upon knowledge that CPUs are numbered sequentially by
+ * cluster - ie. CPUs 0..X will be in cluster 0, CPUs X+1..Y in cluster
+ * 1, CPUs Y+1..Z in cluster 2 etc. This means that CPUs in the same
+ * cluster will immediately precede or follow one another.
+ *
+ * First we scan backwards, until we find an online CPU in the cluster
+ * or we move on to another cluster.
+ */
+ for (i = smp_processor_id() - 1; i >= 0; i--) {
+ if (cpu_cluster(&cpu_data[i]) != local_cl)
+ break;
+ if (!cpu_online(i))
+ continue;
+ return false;
+ }
+
+ /* Then do the same for higher numbered CPUs */
+ for (i = smp_processor_id() + 1; i < nr_cpu_ids; i++) {
+ if (cpu_cluster(&cpu_data[i]) != local_cl)
+ break;
+ if (!cpu_online(i))
+ continue;
+ return false;
+ }
+
+ /* We found no online CPUs in the local cluster */
+ return true;
+}