#include <linux/of.h>
 #include <linux/sched.h>
 
+#include <asm/cputype.h>
 #include <asm/topology.h>
 
 static int __init get_cpu_for_node(struct device_node *node)
         * Check that all cores are in the topology; the SMP code will
         * only mark cores described in the DT as possible.
         */
-       for_each_possible_cpu(cpu) {
-               if (cpu_topology[cpu].cluster_id == -1) {
-                       pr_err("CPU%d: No topology information specified\n",
-                              cpu);
+       for_each_possible_cpu(cpu)
+               if (cpu_topology[cpu].cluster_id == -1)
                        ret = -EINVAL;
-               }
-       }
 
 out_map:
        of_node_put(map);
        struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
        int cpu;
 
-       if (cpuid_topo->cluster_id == -1) {
-               /*
-                * DT does not contain topology information for this cpu.
-                */
-               pr_debug("CPU%u: No topology information configured\n", cpuid);
-               return;
-       }
-
        /* update core and thread sibling masks */
        for_each_possible_cpu(cpu) {
                cpu_topo = &cpu_topology[cpu];
 
 void store_cpu_topology(unsigned int cpuid)
 {
+       struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
+       u64 mpidr;
+
+       if (cpuid_topo->cluster_id != -1)
+               goto topology_populated;
+
+       mpidr = read_cpuid_mpidr();
+
+       /* Uniprocessor systems can rely on default topology values */
+       if (mpidr & MPIDR_UP_BITMASK)
+               return;
+
+       /* Create cpu topology mapping based on MPIDR. */
+       if (mpidr & MPIDR_MT_BITMASK) {
+               /* Multiprocessor system : Multi-threads per core */
+               cpuid_topo->thread_id  = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+               cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+               cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
+       } else {
+               /* Multiprocessor system : Single-thread per core */
+               cpuid_topo->thread_id  = -1;
+               cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+               cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+       }
+
+       pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n",
+                cpuid, cpuid_topo->cluster_id, cpuid_topo->core_id,
+                cpuid_topo->thread_id, mpidr);
+
+topology_populated:
        update_siblings_masks(cpuid);
 }