diff --git a/hdata/cpu-common.c b/hdata/cpu-common.c
index e46f919b7..bf821c154 100644
--- a/hdata/cpu-common.c
+++ b/hdata/cpu-common.c
@@ -46,6 +46,18 @@ struct dt_node * add_core_common(struct dt_node *cpus,
 	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 .. 55 */
 	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 56 .. 63 */
 	};
+	const uint8_t pa_features_p10[] = {
+	       66, 0,
+	       0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xd0, 0x80, 0x00, /*  0 ..  7 */
+	       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*  8 .. 15 */
+	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 16 .. 23 */
+	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 24 .. 31 */
+	       0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, /* 32 .. 39 */
+	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 40 .. 47 */
+	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 .. 55 */
+	       0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 56 .. 63 */
+	       0x80, 0x00,                                     /* 64 .. 65 */
+	};
 
 	const uint8_t *pa_features;
 	size_t pa_features_size;
@@ -83,6 +95,11 @@ struct dt_node * add_core_common(struct dt_node *cpus,
 			pa_features_size = sizeof(pa_features_p9);
 		}
 		break;
+	case PVR_TYPE_P10:
+		name = "PowerPC,POWER10";
+		pa_features = pa_features_p10;
+		pa_features_size = sizeof(pa_features_p10);
+		break;
 	default:
 		name = "PowerPC,Unknown";
 		pa_features = NULL;
@@ -103,7 +120,7 @@ struct dt_node * add_core_common(struct dt_node *cpus,
 	dt_add_property_cells(cpu, "ibm,processor-page-sizes",
 			      0xc, 0x10, 0x18, 0x22);
 
-	if (proc_gen == proc_gen_p9)
+	if (proc_gen >= proc_gen_p9)
 		dt_add_property_cells(cpu, "ibm,processor-radix-AP-encodings",
 			0x0000000c, 0xa0000010, 0x20000015, 0x4000001e);
 
diff --git a/hdata/fsp.c b/hdata/fsp.c
index 18380e7d4..458b7e636 100644
--- a/hdata/fsp.c
+++ b/hdata/fsp.c
@@ -355,7 +355,7 @@ static void add_ipmi_sensors(struct dt_node *bmc_node)
 static void bmc_create_node(const struct HDIF_common_hdr *sp)
 {
 	struct dt_node *bmc_node;
-	u32 fw_bar, io_bar, mem_bar, internal_bar;
+	u32 fw_bar, io_bar, mem_bar, internal_bar, mctp_base;
 	const struct spss_iopath *iopath;
 	const struct spss_sp_impl *sp_impl;
 	struct dt_node *lpcm, *lpc, *n;
@@ -370,7 +370,8 @@ static void bmc_create_node(const struct HDIF_common_hdr *sp)
 	dt_add_property_cells(bmc_node, "#size-cells", 0);
 
 	/* Add sensor info under /bmc */
-	add_ipmi_sensors(bmc_node);
+	if (proc_gen < proc_gen_p10)
+		add_ipmi_sensors(bmc_node);
 
 	sp_impl = HDIF_get_idata(sp, SPSS_IDATA_SP_IMPL, &size);
 	if (CHECK_SPPTR(sp_impl) && (size > 8)) {
@@ -425,12 +426,17 @@ static void bmc_create_node(const struct HDIF_common_hdr *sp)
 	mem_bar = be32_to_cpu(iopath->lpc.memory_bar);
 	io_bar = be32_to_cpu(iopath->lpc.io_bar);
 	internal_bar = be32_to_cpu(iopath->lpc.internal_bar);
+	mctp_base = be32_to_cpu(iopath->lpc.mctp_base);
 
 	prlog(PR_DEBUG, "LPC: IOPATH chip id = %x\n", chip_id);
 	prlog(PR_DEBUG, "LPC: FW BAR       = %#x\n", fw_bar);
 	prlog(PR_DEBUG, "LPC: MEM BAR      = %#x\n", mem_bar);
 	prlog(PR_DEBUG, "LPC: IO BAR       = %#x\n", io_bar);
 	prlog(PR_DEBUG, "LPC: Internal BAR = %#x\n", internal_bar);
+	if (proc_gen >= proc_gen_p10) {
+		/* MCTP is part of FW BAR */
+		prlog(PR_DEBUG, "LPC: MCTP base    = %#x\n", mctp_base);
+	}
 
 	/*
 	 * The internal address space BAR actually points to the LPC master
diff --git a/hdata/i2c.c b/hdata/i2c.c
index 8aa93d8f5..7d5d655a5 100644
--- a/hdata/i2c.c
+++ b/hdata/i2c.c
@@ -250,7 +250,7 @@ int parse_i2c_devs(const struct HDIF_common_hdr *hdr, int idata_index,
 	 * This code makes a few assumptions about XSCOM addrs, etc
 	 * and will need updating for new processors
 	 */
-	assert(proc_gen == proc_gen_p9);
+	assert(proc_gen == proc_gen_p9 || proc_gen == proc_gen_p10);
 
 	/*
 	 * Emit an error if we get a newer version. This is an interim measure
@@ -301,7 +301,8 @@ int parse_i2c_devs(const struct HDIF_common_hdr *hdr, int idata_index,
 		 * engines outside this range so we don't create bogus
 		 * i2cm@<addr> nodes.
 		 */
-		if (dev->i2cm_engine >= 4 && proc_gen == proc_gen_p9)
+		if (dev->i2cm_engine >= 4 &&
+			(proc_gen == proc_gen_p9 || proc_gen == proc_gen_p10))
 			continue;
 
 		bus = p8_i2c_add_port_node(xscom, dev->i2cm_engine, dev->i2cm_port,
diff --git a/hdata/iohub.c b/hdata/iohub.c
index fa3afbf7a..fb215e1fb 100644
--- a/hdata/iohub.c
+++ b/hdata/iohub.c
@@ -151,6 +151,7 @@ static struct dt_node *add_pec_stack(const struct cechub_io_hub *hub,
 				     int phb_index, u8 active_phbs)
 {
 	struct dt_node *stack;
+	const char *compat;
 	u64 eq[8];
 	u8 *gen4;
 	int i;
@@ -158,9 +159,14 @@ static struct dt_node *add_pec_stack(const struct cechub_io_hub *hub,
 	stack = dt_new_addr(pbcq, "stack", stack_index);
 	assert(stack);
 
+	if (proc_gen == proc_gen_p9)
+		compat = "ibm,power9-phb-stack";
+	else
+		compat = "ibm,power10-phb-stack";
+
 	dt_add_property_cells(stack, "reg", stack_index);
 	dt_add_property_cells(stack, "ibm,phb-index", phb_index);
-	dt_add_property_string(stack, "compatible", "ibm,power9-phb-stack");
+	dt_add_property_string(stack, "compatible", compat);
 
 	/* XXX: This should probably just return if the PHB is disabled
 	 *      rather than adding the extra properties.
@@ -190,6 +196,7 @@ static struct dt_node *add_pec_stack(const struct cechub_io_hub *hub,
 	return stack;
 }
 
+/* Add PHB4 on p9, PHB5 on p10 */
 static struct dt_node *io_add_phb4(const struct cechub_io_hub *hub,
 				   const struct HDIF_common_hdr *sp_iohubs,
 				   struct dt_node *xcom,
@@ -199,10 +206,21 @@ static struct dt_node *io_add_phb4(const struct cechub_io_hub *hub,
 {
 	struct dt_node *pbcq;
 	uint8_t active_phb_mask = hub->fab_br0_pdt;
-	uint32_t pe_xscom  = 0x4010c00 + (pec_index * 0x0000400);
-	uint32_t pci_xscom = 0xd010800 + (pec_index * 0x1000000);
+	uint32_t pe_xscom;
+	uint32_t pci_xscom;
+	const char *compat;
 	int i;
 
+	if (proc_gen == proc_gen_p9) {
+		pe_xscom  = 0x4010c00 + (pec_index * 0x0000400);
+		pci_xscom = 0xd010800 + (pec_index * 0x1000000);
+		compat = "ibm,power9-pbcq";
+	} else {
+		pe_xscom  = 0x3011800 - (pec_index * 0x1000000);
+		pci_xscom = 0x8010800 + (pec_index * 0x1000000);
+		compat = "ibm,power10-pbcq";
+	}
+
 	/* Create PBCQ node under xscom */
 	pbcq = dt_new_addr(xcom, "pbcq", pe_xscom);
 	if (!pbcq)
@@ -214,7 +232,7 @@ static struct dt_node *io_add_phb4(const struct cechub_io_hub *hub,
 				pci_xscom, 0x200);
 
 	/* The hubs themselves go under the stacks */
-	dt_add_property_strings(pbcq, "compatible", "ibm,power9-pbcq");
+	dt_add_property_strings(pbcq, "compatible", compat);
 	dt_add_property_cells(pbcq, "ibm,pec-index", pec_index);
 	dt_add_property_cells(pbcq, "#address-cells", 1);
 	dt_add_property_cells(pbcq, "#size-cells", 0);
@@ -229,7 +247,7 @@ static struct dt_node *io_add_phb4(const struct cechub_io_hub *hub,
 	 */
 	io_get_loc_code(sp_iohubs, pbcq, "ibm,loc-code");
 
-	prlog(PR_INFO, "CEC: Added PHB4 PBCQ %d with %d stacks\n",
+	prlog(PR_INFO, "CEC: Added PBCQ %d with %d stacks\n",
 		pec_index, stacks);
 
 	/* the actual PHB nodes created later on by skiboot */
@@ -267,6 +285,7 @@ static struct dt_node *io_add_p8(const struct cechub_io_hub *hub,
 	return xscom;
 }
 
+/* Add PBCQs for p9/p10 */
 static struct dt_node *io_add_p9(const struct cechub_io_hub *hub,
 				 const struct HDIF_common_hdr *sp_iohubs)
 {
@@ -280,17 +299,22 @@ static struct dt_node *io_add_p9(const struct cechub_io_hub *hub,
 
 	xscom = find_xscom_for_chip(chip_id);
 	if (!xscom) {
-		prerror("P9: Can't find XSCOM for chip %d\n", chip_id);
+		prerror("IOHUB: Can't find XSCOM for chip %d\n", chip_id);
 		return NULL;
 	}
 
-	prlog(PR_DEBUG, "IOHUB: PHB4 active bridge mask %x\n",
+	prlog(PR_DEBUG, "IOHUB: PHB active bridge mask %x\n",
 		(u32) hub->fab_br0_pdt);
 
 	/* Create PBCQs */
-	io_add_phb4(hub, sp_iohubs, xscom, 0, 1, 0);
-	io_add_phb4(hub, sp_iohubs, xscom, 1, 2, 1);
-	io_add_phb4(hub, sp_iohubs, xscom, 2, 3, 3);
+	if (proc_gen == proc_gen_p9) {
+		io_add_phb4(hub, sp_iohubs, xscom, 0, 1, 0);
+		io_add_phb4(hub, sp_iohubs, xscom, 1, 2, 1);
+		io_add_phb4(hub, sp_iohubs, xscom, 2, 3, 3);
+	} else { /* p10 */
+		io_add_phb4(hub, sp_iohubs, xscom, 0, 3, 0);
+		io_add_phb4(hub, sp_iohubs, xscom, 1, 3, 3);
+	}
 
 	return xscom;
 }
@@ -806,6 +830,10 @@ static void io_parse_fru(const void *sp_iohubs)
 			prlog(PR_INFO, "CEC:     Axone !\n");
 			io_add_p9(hub, sp_iohubs);
 			break;
+		case CECHUB_HUB_RAINIER:
+			prlog(PR_INFO, "CEC:     Rainier !\n");
+			io_add_p9(hub, sp_iohubs);
+			break;
 		default:
 			prlog(PR_ERR, "CEC:     Hub ID 0x%04x unsupported !\n",
 			      hub_id);
@@ -817,7 +845,7 @@ static void io_parse_fru(const void *sp_iohubs)
 		io_parse_slots(sp_iohubs, chip_id);
 	}
 
-	if (proc_gen == proc_gen_p8 || proc_gen == proc_gen_p9)
+	if (proc_gen == proc_gen_p8 || proc_gen == proc_gen_p9 || proc_gen == proc_gen_p10)
 		io_add_p8_cec_vpd(sp_iohubs);
 }
 
diff --git a/hdata/memory.c b/hdata/memory.c
index 6602addd9..efdb502b1 100755
--- a/hdata/memory.c
+++ b/hdata/memory.c
@@ -53,6 +53,8 @@ struct HDIF_ms_area_address_range {
 #define   PHYS_ATTR_STATUS_SAVE_FAILED	0x02
 #define   PHYS_ATTR_STATUS_SAVED	0x04
 #define   PHYS_ATTR_STATUS_NOT_SAVED	0x08
+#define   PHYS_ATTR_STATUS_ENCRYPTED	0x10
+#define   PHYS_ATTR_STATUS_ERR_DETECTED	0x40
 #define   PHYS_ATTR_STATUS_MEM_INVALID	0xff
 
 /* Memory Controller ID for Nimbus P9 systems */
@@ -514,7 +516,7 @@ static void add_memory_buffer_mmio(const struct HDIF_common_hdr *msarea)
 	struct dt_node *membuf;
 	beint64_t *reg, *flags;
 
-	if (PVR_TYPE(mfspr(SPR_PVR)) != PVR_TYPE_P9P)
+	if (proc_gen <= proc_gen_p9 && PVR_TYPE(mfspr(SPR_PVR)) != PVR_TYPE_P9P)
 		return;
 
 	if (be16_to_cpu(msarea->version) < 0x50) {
@@ -911,7 +913,8 @@ static bool __memory_parse(struct dt_node *root)
 	prlog(PR_DEBUG, "MS VPD: is at %p\n", ms_vpd);
 
 	msac = HDIF_get_idata(ms_vpd, MSVPD_IDATA_MS_ADDR_CONFIG, &size);
-	if (!CHECK_SPPTR(msac) || size < sizeof(*msac)) {
+	if (!CHECK_SPPTR(msac) ||
+	    size < offsetof(struct msvpd_ms_addr_config, max_possible_ms_address)) {
 		prerror("MS VPD: bad msac size %u @ %p\n", size, msac);
 		op_display(OP_FATAL, OP_MOD_MEM, 0x0002);
 		return false;
@@ -953,4 +956,3 @@ void memory_parse(void)
 		abort();
 	}
 }
-
diff --git a/hdata/spira.c b/hdata/spira.c
index 2e3b3a463..85c2fe71c 100644
--- a/hdata/spira.c
+++ b/hdata/spira.c
@@ -301,6 +301,7 @@ static struct dt_node *add_xscom_node(uint64_t base, uint32_t hw_id,
 		addr = base | ((uint64_t)hw_id << PPC_BITLSHIFT(28));
 		break;
 	case proc_gen_p9:
+	case proc_gen_p10: /* XXX P10 */
 	default:
 		/* On P9 we need to put the chip ID in the natural powerbus
 		 * position.
@@ -332,6 +333,10 @@ static struct dt_node *add_xscom_node(uint64_t base, uint32_t hw_id,
 		dt_add_property_strings(node, "compatible",
 					"ibm,xscom", "ibm,power9-xscom");
 		break;
+	case proc_gen_p10:
+		dt_add_property_strings(node, "compatible",
+					"ibm,xscom", "ibm,power10-xscom");
+		break;
 	default:
 		dt_add_property_strings(node, "compatible", "ibm,xscom");
 	}
@@ -420,6 +425,11 @@ static void add_psihb_node(struct dt_node *np)
 		psi_slen = 0x100;
 		psi_comp = "ibm,power9-psihb-x";
 		break;
+	case proc_gen_p10:
+		psi_scom = 0x3011d00;
+		psi_slen = 0x100;
+		psi_comp = "ibm,power10-psihb-x";
+		break;
 	default:
 		psi_comp = NULL;
 	}
@@ -438,10 +448,28 @@ static void add_psihb_node(struct dt_node *np)
 
 static void add_xive_node(struct dt_node *np)
 {
-	struct dt_node *xive = dt_new_addr(np, "xive", 0x5013000);
+	struct dt_node *xive;
+	const char *comp;
+	u32 scom, slen;
+
+	switch (proc_gen) {
+	case proc_gen_p9:
+		scom = 0x5013000;
+		slen = 0x300;
+		comp = "ibm,power9-xive-x";
+		break;
+	case proc_gen_p10:
+		scom = 0x2010800;
+		slen = 0x400;
+		comp = "ibm,power10-xive-x";
+		break;
+	default:
+		return;
+	}
 
-	dt_add_property_cells(xive, "reg", 0x5013000, 0x300);
-	dt_add_property_string(xive, "compatible", "ibm,power9-xive-x");
+	xive = dt_new_addr(np, "xive", scom);
+	dt_add_property_cells(xive, "reg", scom, slen);
+	dt_add_property_string(xive, "compatible", comp);
 
 	/* HACK: required for simics */
 	dt_add_property(xive, "force-assign-bars", NULL, 0);
@@ -725,6 +753,9 @@ static void add_chiptod_node(unsigned int chip_id, int flags)
 	case proc_gen_p9:
 		compat_str = "ibm,power9-chiptod";
 		break;
+	case proc_gen_p10:
+		compat_str = "ibm,power10-chiptod";
+		break;
 	default:
 		return;
 	}
@@ -866,6 +897,7 @@ static void add_nx_node(u32 gcid)
 		/* POWER9 NX is not software compatible with P8 NX */
 		dt_add_property_strings(nx, "compatible", "ibm,power9-nx");
 		break;
+	case proc_gen_p10: /* XXX P10 */
 	default:
 		return;
 	}
@@ -903,15 +935,21 @@ static void add_nx(void)
 static void add_nmmu(void)
 {
 	struct dt_node *xscom, *nmmu;
+	u32 scom;
 
-	/* Nest MMU only exists on POWER9 */
-	if (proc_gen != proc_gen_p9)
+	/* Nest MMU only exists on POWER9 or later */
+	if (proc_gen < proc_gen_p9)
 		return;
 
+	if (proc_gen == proc_gen_p9)
+		scom = 0x5012c40;
+	else
+		scom = 0x2010c40;
+
 	dt_for_each_compatible(dt_root, xscom, "ibm,xscom") {
-		nmmu = dt_new_addr(xscom, "nmmu", 0x5012c40);
+		nmmu = dt_new_addr(xscom, "nmmu", scom);
 		dt_add_property_strings(nmmu, "compatible", "ibm,power9-nest-mmu");
-		dt_add_property_cells(nmmu, "reg", 0x5012c40, 0x20);
+		dt_add_property_cells(nmmu, "reg", scom, 0x20);
 	}
 }
 
diff --git a/hdata/spira.h b/hdata/spira.h
index 18d73bdfa..7c5341f94 100644
--- a/hdata/spira.h
+++ b/hdata/spira.h
@@ -304,7 +304,7 @@ struct spss_iopath {
 			__be32	firmware_bar;
 			__be32	internal_bar;
 
-			__be32	reserved2;
+			__be32	mctp_base;
 
 			__be64	uart_base;
 			__be32	uart_size;
@@ -316,13 +316,27 @@ struct spss_iopath {
 #define			UART_INT_LVL_LOW	0x1
 #define			UART_INT_RISING		0x2
 #define			UART_INT_LVL_HIGH	0x3
-			uint8_t reserved3[2];
+			uint8_t uart_valid;
+			uint8_t reserved3;
 
 			__be64	bt_base;
 			__be32	bt_size;
 			uint8_t	bt_sms_int_num;
 			uint8_t	bt_bmc_response_int_num;
 			uint8_t	reserved4[2];
+
+			__be16	kcs_data_reg_addr;
+			__be16	kcs_status_reg_addr;
+			uint8_t kcs_int_number;
+
+			__be64	uart2_base;
+			__be32	uart2_size;
+			__be32	uart2_clk;  /* UART baud clock in Hz */
+			__be32	uart2_baud; /* UART baud rate */
+			uint8_t uart2_int_number;
+			uint8_t uart2_int_type;
+			uint8_t uart2_valid;
+			uint8_t reserved5;
 		} __packed lpc;
 	};
 } __packed;
@@ -493,6 +507,7 @@ struct msvpd_ms_addr_config {
 	__be64	 max_possible_ms_address;
 	__be32	 deprecated;
 	__be64	 mirrorable_memory_starting_address;
+	__be64	 hrmor_stash_loc_address;
 } __packed;
 
 /* Idata index 1: Total configured mainstore */
@@ -651,6 +666,7 @@ struct cechub_io_hub {
 #define CECHUB_HUB_NIMBUS_LAGRANGE	0x0022	/* Nimbus+lagrange from spec */
 #define CECHUB_HUB_CUMULUS_DUOMO	0x0030	/* cumulus+duomo from spec */
 #define CECHUB_HUB_AXONE_HOPPER		0x0040	/* axone+hopper */
+#define CECHUB_HUB_RAINIER		0x0050
 	__be32		ec_level;
 	__be32		aff_dom2;	/* HDAT < v9.x only */
 	__be32		aff_dom3;	/* HDAT < v9.x only */
diff --git a/hdata/test/hdata_to_dt.c b/hdata/test/hdata_to_dt.c
index 90d83f937..1729f1ca9 100644
--- a/hdata/test/hdata_to_dt.c
+++ b/hdata/test/hdata_to_dt.c
@@ -2,7 +2,7 @@
 /*
  * Given a hdata dump, output the device tree.
  *
- * Copyright 2013-2019 IBM Corp.
+ * Copyright 2013-2020 IBM Corp.
  */
 
 #include <sys/types.h>
@@ -63,11 +63,13 @@ unsigned long tb_hz = 512000000;
 #define PVR_TYPE_P8NVL	0x004c
 #define PVR_TYPE_P9	0x004e
 #define PVR_TYPE_P9P	0x004f
+#define PVR_TYPE_P10	0x0080
 #define PVR_P8E		0x004b0201
 #define PVR_P8		0x004d0200
 #define PVR_P8NVL	0x004c0100
 #define PVR_P9		0x004e0200
 #define PVR_P9P		0x004f0100
+#define PVR_P10		0x00800100
 
 #define SPR_PVR		0x11f	/* RO: Processor version register */
 
@@ -328,6 +330,10 @@ int main(int argc, char *argv[])
 			fake_pvr = PVR_P9P;
 			proc_gen = proc_gen_p9;
 			opt_count++;
+		} else if (strcmp(argv[i], "-10") == 0) {
+			fake_pvr = PVR_P10;
+			proc_gen = proc_gen_p10;
+			opt_count++;
 		}
 	}
 
@@ -347,13 +353,17 @@ int main(int argc, char *argv[])
 		     "  -8 Force PVR to POWER8\n"
 		     "  -8E Force PVR to POWER8E\n"
 		     "  -9 Force PVR to POWER9 (nimbus)\n"
+		     "  -9P Force PVR to POWER9P (Axone)\n"
+		     "  -10 Force PVR to POWER10\n"
 		     "\n"
 		     "When no PVR is specified -8 is assumed"
 		     "\n"
 		     "Pipe to 'dtc -I dtb -O dts' for human readable output\n");
 	}
 
-	phys_map_init(fake_pvr);
+	/* We don't have phys mapping for P8 */
+	if (proc_gen != proc_gen_p8)
+		phys_map_init(fake_pvr);
 
 	/* Copy in spira dump (assumes little has changed!). */
 	if (new_spira) {
