* Individual features below.
  */
 
+/*
+ * Support for memory protection keys.
+ */
+#define MMU_FTR_PKEY                   ASM_CONST(0x00000800)
+
 /* Guest Translation Shootdown Enable */
 #define MMU_FTR_GTSE                   ASM_CONST(0x00001000)
 
                MMU_FTR_RADIX_KUAP |
 #endif /* CONFIG_PPC_KUAP */
 #endif /* CONFIG_PPC_RADIX_MMU */
+#ifdef CONFIG_PPC_MEM_KEYS
+       MMU_FTR_PKEY |
+#endif
                0,
 };
 
                                       phys_addr_t first_memblock_size);
 static inline void mmu_early_init_devtree(void) { }
 
+static inline void pkey_early_init_devtree(void) {}
+
 extern void *abatron_pteptrs[2];
 #endif /* __ASSEMBLY__ */
 #endif
 
 #include <asm/mmu.h>
 #include <asm/setup.h>
 #include <linux/pkeys.h>
-#include <linux/of_device.h>
+#include <linux/of_fdt.h>
+
 
 DEFINE_STATIC_KEY_FALSE(pkey_disabled);
 int  num_pkey;         /* Max number of pkeys supported */
 #define PKEY_REG_BITS (sizeof(u64) * 8)
 #define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey+1) * AMR_BITS_PER_PKEY))
 
+static int __init dt_scan_storage_keys(unsigned long node,
+                                      const char *uname, int depth,
+                                      void *data)
+{
+       const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+       const __be32 *prop;
+       int *pkeys_total = (int *) data;
+
+       /* We are scanning "cpu" nodes only */
+       if (type == NULL || strcmp(type, "cpu") != 0)
+               return 0;
+
+       prop = of_get_flat_dt_prop(node, "ibm,processor-storage-keys", NULL);
+       if (!prop)
+               return 0;
+       *pkeys_total = be32_to_cpu(prop[0]);
+       return 1;
+}
+
 static int scan_pkey_feature(void)
 {
-       u32 vals[2];
+       int ret;
        int pkeys_total = 0;
-       struct device_node *cpu;
 
        /*
         * Pkey is not supported with Radix translation.
         */
-       if (radix_enabled())
-               return 0;
-
-       cpu = of_find_node_by_type(NULL, "cpu");
-       if (!cpu)
+       if (early_radix_enabled())
                return 0;
 
-       if (of_property_read_u32_array(cpu,
-                                      "ibm,processor-storage-keys", vals, 2) == 0) {
-               /*
-                * Since any pkey can be used for data or execute, we will
-                * just treat all keys as equal and track them as one entity.
-                */
-               pkeys_total = vals[0];
-       } else {
-
+       ret = of_scan_flat_dt(dt_scan_storage_keys, &pkeys_total);
+       if (ret == 0) {
                /*
                 * Let's assume 32 pkeys on P8/P9 bare metal, if its not defined by device
                 * tree. We make this exception since some version of skiboot forgot to
        return pkeys_total;
 }
 
-static int pkey_initialize(void)
+void __init pkey_early_init_devtree(void)
 {
        int pkeys_total, i;
 
        if (!pkeys_total) {
                /* No support for pkey. Mark it disabled */
                static_branch_enable(&pkey_disabled);
-               return 0;
+               return;
        }
 
+       cur_cpu_spec->mmu_features |= MMU_FTR_PKEY;
+
        /*
         * The device tree cannot be relied to indicate support for
         * execute_disable support. Instead we use a PVR check.
         */
        initial_allocation_mask |= reserved_allocation_mask;
 
-       return 0;
+       return;
 }
 
-arch_initcall(pkey_initialize);
-
 void pkey_mm_init(struct mm_struct *mm)
 {
        if (static_branch_likely(&pkey_disabled))