diff mbox

[RESEND,V6,3/5] capi: Enable capi mode for PHB4

Message ID 1497356482-6731-4-git-send-email-clombard@linux.vnet.ibm.com
State Accepted
Headers show

Commit Message

Christophe Lombard June 13, 2017, 12:21 p.m. UTC
Enable the Coherently attached processor interface. The PHB is used as
a CAPI interface.
CAPI Adapters can be connected to either PEC0 or PEC2. Single port
CAPI adapter can be connected to either PEC0 or PEC2, but Dual-Port
Adapter can be only connected to PEC2
   CAPP0 attached to PHB0(PEC0 - single port)
   CAPP1 attached to PHB3(PEC2 - single or dual port)
As we did for PHB3, a new specific file 'phb4-capp.h' is created to
contain the CAPP register definitions.

Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
---
 hw/phb4.c           | 359 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 include/chip.h      |   1 +
 include/opal-api.h  |   1 +
 include/phb4-capp.h |  60 +++++++++
 include/phb4-regs.h |   7 +-
 5 files changed, 422 insertions(+), 6 deletions(-)
 create mode 100644 include/phb4-capp.h

Comments

Frederic Barrat June 14, 2017, 5:44 p.m. UTC | #1
Le 13/06/2017 à 14:21, Christophe Lombard a écrit :
> Enable the Coherently attached processor interface. The PHB is used as
> a CAPI interface.
> CAPI Adapters can be connected to either PEC0 or PEC2. Single port
> CAPI adapter can be connected to either PEC0 or PEC2, but Dual-Port
> Adapter can be only connected to PEC2
>     CAPP0 attached to PHB0(PEC0 - single port)
>     CAPP1 attached to PHB3(PEC2 - single or dual port)
> As we did for PHB3, a new specific file 'phb4-capp.h' is created to
> contain the CAPP register definitions.
> 
> Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
> ---

Thanks for the modifications, looks ok to me.
Reviewed-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>



>   hw/phb4.c           | 359 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>   include/chip.h      |   1 +
>   include/opal-api.h  |   1 +
>   include/phb4-capp.h |  60 +++++++++
>   include/phb4-regs.h |   7 +-
>   5 files changed, 422 insertions(+), 6 deletions(-)
>   create mode 100644 include/phb4-capp.h
> 
> diff --git a/hw/phb4.c b/hw/phb4.c
> index 3843456..5ea6138 100644
> --- a/hw/phb4.c
> +++ b/hw/phb4.c
> @@ -47,7 +47,7 @@
>   #include <affinity.h>
>   #include <phb4.h>
>   #include <phb4-regs.h>
> -#include <capp.h>
> +#include <phb4-capp.h>
>   #include <fsp.h>
>   #include <chip.h>
>   #include <chiptod.h>
> @@ -77,6 +77,11 @@ static void phb4_init_hw(struct phb4 *p, bool first_init);
>   #define PHBLOGCFG(p, fmt, a...) do {} while (0)
>   #endif
> 
> +enum capi_dma_tvt {
> +	CAPI_DMA_TVT0,
> +	CAPI_DMA_TVT1,
> +};
> +
>   /* Note: The "ASB" name is historical, practically this means access via
>    * the XSCOM backdoor
>    */
> @@ -2111,6 +2116,8 @@ static int64_t phb4_freset(struct pci_slot *slot)
>   	return OPAL_HARDWARE;
>   }
> 
> +extern struct lock capi_lock;
> +
>   static int64_t phb4_creset(struct pci_slot *slot)
>   {
>   	struct phb4 *p = phb_to_phb4(slot->phb);
> @@ -2509,6 +2516,344 @@ static int64_t phb4_get_diag_data(struct phb *phb,
>   	return OPAL_SUCCESS;
>   }
> 
> +static uint64_t tve_encode_50b_noxlate(uint64_t start_addr, uint64_t end_addr)
> +{
> +	uint64_t tve;
> +
> +	/*
> +	 * Put start address bits 49:24 into TVE[52:53]||[0:23]
> +	 * and end address bits 49:24 into TVE[54:55]||[24:47]
> +	 * and set TVE[51]
> +	 */
> +	tve  = (start_addr << 16) & (0xffffffull << 40);
> +	tve |= (start_addr >> 38) & (3ull << 10);
> +	tve |= (end_addr >>  8) & (0xfffffful << 16);
> +	tve |= (end_addr >> 40) & (3ull << 8);
> +	tve |= PPC_BIT(51) | IODA3_TVT_NON_TRANSLATE_50;
> +	return tve;
> +}
> +
> +static void phb4_init_capp_regs(struct phb4 *p)
> +{
> +	uint64_t reg;
> +	uint32_t offset;
> +
> +	offset = PHB4_CAPP_REG_OFFSET(p);
> +
> +	/* Enable cresp examination by CAPP */
> +	xscom_read(p->chip_id, APC_MASTER_PB_CTRL + offset, &reg);
> +	reg |= PPC_BIT(0);
> +	if (p->rev == PHB4_REV_NIMBUS_DD10) {
> +		reg |= PPC_BIT(1);
> +		/* disable vg not sys */
> +		reg |= PPC_BIT(3);
> +	}
> +	xscom_write(p->chip_id, APC_MASTER_PB_CTRL + offset, reg);
> +
> +	/* Set PHB mode, HPC Dir State and P9 mode */
> +	xscom_write(p->chip_id, APC_MASTER_CAPI_CTRL + offset,
> +		    0x1772000000000000);
> +	PHBINF(p, "CAPP: port attached\n");
> +
> +	/* Set snoop ttype decoding , dir size to 256k */
> +	xscom_write(p->chip_id, SNOOP_CAPI_CONFIG + offset, 0xA000000000000000);
> +
> +	/* Use Read Epsilon Tier2 for all scopes, Address Pipeline Master
> +	 * Wait Count to highest(1023) and Number of rpt_hang.data to 3
> +	 */
> +	xscom_write(p->chip_id, SNOOP_CONTROL + offset, 0x8000000010072000);
> +
> +	/* TLBI Hang Divider = 16.  CI Store Buffer Threshold initialized
> +	 * to b’0101’ = use 6 buffers. X16 PCIe(14 buffers)
> +	 */
> +	xscom_read(p->chip_id, TRANSPORT_CONTROL + offset, &reg);
> +	if (!(reg & PPC_BIT(4))) {
> +		if (p->index == CAPP0_PHB_INDEX)
> +			xscom_write(p->chip_id, TRANSPORT_CONTROL + offset,
> +				    0x081400000000000A);
> +
> +		if (p->index == CAPP1_PHB_INDEX)
> +			xscom_write(p->chip_id, TRANSPORT_CONTROL + offset,
> +				    0x0814000000000008);
> +
> +		/* Initialize CI Store Buffers */
> +		xscom_read(p->chip_id, TRANSPORT_CONTROL + offset, &reg);
> +		reg |= PPC_BIT(63);
> +		xscom_write(p->chip_id, TRANSPORT_CONTROL + offset, reg);
> +	}
> +
> +	/* Enable epoch timer */
> +	xscom_write(p->chip_id, EPOCH_RECOVERY_TIMERS_CTRL + offset,
> +		    0xC0000000FFF0FFFE);
> +
> +	xscom_write(p->chip_id, FLUSH_SUE_STATE_MAP + offset,
> +		    0x1DCF5F6600000000);
> +	xscom_write(p->chip_id, FLUSH_SUE_UOP1 + offset, 0xE310280428000000);
> +
> +	/* capp owns PHB read buffers */
> +	if (p->index == CAPP0_PHB_INDEX) {
> +		xscom_write(p->chip_id, APC_FSM_READ_MASK + offset,
> +			    0xFFFFFFFFFFFF0000);
> +		xscom_write(p->chip_id, XPT_FSM_RMM + offset,
> +			    0xFFFFFFFFFFFF0000);
> +	}
> +	if (p->index == CAPP1_PHB_INDEX) {
> +		xscom_write(p->chip_id, APC_FSM_READ_MASK + offset,
> +			    0xFFFFFFFE00000000);
> +		xscom_write(p->chip_id, XPT_FSM_RMM + offset,
> +			    0xFFFFFFFE00000000);
> +	}
> +
> +	/* Deassert TLBI_FENCED and tlbi_psl_is_dead */
> +	xscom_write(p->chip_id, CAPP_ERR_STATUS_CTRL + offset, 0);
> +}
> +
> +/* override some inits with CAPI defaults */
> +static void phb4_init_capp_errors(struct phb4 *p)
> +{
> +	/* Init_77: TXE Error AIB Fence Enable Register */
> +	out_be64(p->regs + 0x0d30,	0xdff7ff0bf7ddfff0ull);
> +
> +	/* Init_86: RXE_ARB Error AIB Fence Enable Register */
> +	out_be64(p->regs + 0x0db0,	0xfbffd7bbff7fbfefull);
> +
> +	/* Init_95: RXE_MRG Error AIB Fence Enable Register */
> +	out_be64(p->regs + 0x0e30,	0xfffffeffff7fff57ull);
> +
> +	/* Init_104: RXE_TCE Error AIB Fence Enable Register */
> +	out_be64(p->regs + 0x0eb0,	0xffaeffafffffffffull);
> +
> +	/* Init_113: PHB Error AIB Fence Enable Register */
> +	out_be64(p->regs + 0x0cb0,	0x35777073ff000000ull);
> +}
> +
> +/* Power Bus Common Queue Registers
> + * All PBCQ and PBAIB registers are accessed via SCOM
> + * NestBase = 4010C00 for PEC0
> + *            4011000 for PEC1
> + *            4011400 for PEC2
> + *
> + * Some registers are shared amongst all of the stacks and will only
> + * have 1 copy. Other registers are implemented one per stack.
> + * Registers that are duplicated will have an additional offset
> + * of “StackBase” so that they have a unique address.
> + * Stackoffset = 00000040 for Stack0
> + *             = 00000080 for Stack1
> + *             = 000000C0 for Stack2
> + */
> +static int64_t enable_capi_mode(struct phb4 *p, uint64_t pe_number,
> +				enum capi_dma_tvt dma_tvt)
> +{
> +	uint64_t reg, start_addr, end_addr;
> +	uint32_t offset;
> +	int i;
> +
> +	xscom_read(p->chip_id, p->pe_xscom + 0x7, &reg);
> +	if (reg & PPC_BIT(0))
> +		PHBDBG(p, "Already in CAPP mode\n");
> +
> +	/* PEC Phase 3 (PBCQ) registers Init */
> +	/* poll cqstat
> +	 * CAPP0 attached to PHB0(PEC0)
> +	 * CAPP1 attached to PHB3(PEC2)
> +	 */
> +	if (p->index == 0) {
> +		/* PEC 0 */
> +		offset = 0x40;
> +	} else if (p->index == 1 || p->index == 2) {
> +		/* PEC 1 */
> +		offset = 0x80;
> +	} else {
> +		/* PEC 2 */
> +		offset = 0xC0;
> +	}
> +
> +	for (i = 0; i < 500000; i++) {
> +		xscom_read(p->chip_id, p->pe_xscom + offset + 0xC, &reg);
> +		if (!(reg & 0xC000000000000000))
> +			break;
> +		time_wait_us(10);
> +	}
> +	if (reg & 0xC000000000000000) {
> +		PHBERR(p, "CAPP: Timeout waiting for pending transaction\n");
> +		return OPAL_HARDWARE;
> +	}
> +
> +	/* Enable CAPP Mode , Set 14 CI Store buffers for CAPP,
> +	 * Set 48 Read machines for CAPP.
> +	 */
> +	if (p->index == CAPP0_PHB_INDEX)
> +		reg = 0x800EFFFFFFFFFFFF;
> +
> +	if (p->index == CAPP1_PHB_INDEX)
> +		reg = 0x8006FFFFFFFE0000;
> +	xscom_write(p->chip_id, p->pe_xscom + 0x7, reg);
> +
> +	if (p->rev == PHB4_REV_NIMBUS_DD10) {
> +		/* Ignores the PB init signal */
> +		xscom_read(p->chip_id, p->pe_xscom + 0x0, &reg);
> +		reg |= PPC_BIT(12);
> +		xscom_write(p->chip_id, p->pe_xscom + 0x0, reg);
> +	}
> +
> +	/* PEC Phase 4 (PHB) registers adjustment
> +	 * Bit [0:7] XSL_DSNCTL[capiind]
> +	 * Init_25 - CAPI Compare/Mask
> +	 */
> +	out_be64(p->regs + PHB_CAPI_CMPM,
> +		 0x0200FE0000000000Ull | PHB_CAPI_CMPM_ENABLE);
> +
> +	if (!(p->rev == PHB4_REV_NIMBUS_DD10)) {
> +		/* Init_123 :  NBW Compare/Mask Register */
> +		out_be64(p->regs + PHB_PBL_NBW_CMP_MASK,
> +			 0x0300FF0000000000Ull | PHB_PBL_NBW_MASK_ENABLE);
> +
> +		/* Init_24 - ASN Compare/Mask */
> +		out_be64(p->regs + PHB_PBL_ASN_CMPM,
> +			 0x0400FF0000000000Ull | PHB_PBL_ASN_ENABLE);
> +	}
> +
> +	/* non-translate/50-bit mode */
> +	out_be64(p->regs + PHB_NXLATE_PREFIX, 0x0000000000000000Ull);
> +
> +	/* set tve no translate mode allow mmio window */
> +	memset(p->tve_cache, 0x0, sizeof(p->tve_cache));
> +
> +	/*
> +	 * In 50-bit non-translate mode, the fields of the TVE are
> +	 * used to perform an address range check. In this mode TCE
> +	 * Table Size(0) must be a '1' (TVE[51] = 1)
> +	 *      PCI Addr(49:24) >= TVE[52:53]+TVE[0:23] and
> +	 *      PCI Addr(49:24) < TVE[54:55]+TVE[24:47]
> +	 *
> +	 * TVE[51] = 1
> +	 * TVE[56] = 1: 50-bit Non-Translate Mode Enable
> +	 * TVE[0:23] = 0x000000
> +	 * TVE[24:47] = 0xFFFFFF
> +	 *
> +	 * capi dma mode: CAPP DMA mode needs access to all of memory
> +	 * capi mode: Allow address range (bit 14 = 1)
> +	 *            0x0002000000000000: 0x0002FFFFFFFFFFFF
> +	 *            TVE[52:53] = '10' and TVE[54:55] = '10'
> +	 */
> +
> +	/* TVT#0: CAPI window + DMA, all memory */
> +	start_addr = 0ull;
> +	end_addr   = 0x0003ffffffffffffull;
> +	p->tve_cache[pe_number * 2] =
> +		tve_encode_50b_noxlate(start_addr, end_addr);
> +
> +	/* TVT#1: DMA, all memory, in bypass mode */
> +	if (dma_tvt == CAPI_DMA_TVT1) {
> +		start_addr = (1ull << 59);
> +		end_addr   = start_addr + 0x0003ffffffffffffull;
> +		p->tve_cache[pe_number * 2 + 1] =
> +			tve_encode_50b_noxlate(start_addr, end_addr);
> +	}
> +
> +	phb4_ioda_sel(p, IODA3_TBL_TVT, 0, true);
> +	for (i = 0; i < p->tvt_size; i++)
> +		out_be64(p->regs + PHB_IODA_DATA0, p->tve_cache[i]);
> +
> +	/* set mbt bar to pass capi mmio window. First applied cleared
> +	 * values to HW
> +	 */
> +	for (i = 0; i < p->mbt_size; i++) {
> +		p->mbt_cache[i][0] = 0;
> +		p->mbt_cache[i][1] = 0;
> +	}
> +	phb4_ioda_sel(p, IODA3_TBL_MBT, 0, true);
> +	for (i = 0; i < p->mbt_size; i++) {
> +		out_be64(p->regs + PHB_IODA_DATA0, p->mbt_cache[i][0]);
> +		out_be64(p->regs + PHB_IODA_DATA0, p->mbt_cache[i][1]);
> +	}
> +
> +	p->mbt_cache[0][0] = IODA3_MBT0_ENABLE |
> +			     IODA3_MBT0_TYPE_M64 |
> +		SETFIELD(IODA3_MBT0_MODE, 0ull, IODA3_MBT0_MODE_SINGLE_PE) |
> +		SETFIELD(IODA3_MBT0_MDT_COLUMN, 0ull, 0) |
> +		(p->mm0_base & IODA3_MBT0_BASE_ADDR);
> +	p->mbt_cache[0][1] = IODA3_MBT1_ENABLE |
> +		((~(p->mm0_size - 1)) & IODA3_MBT1_MASK) |
> +		SETFIELD(IODA3_MBT1_SINGLE_PE_NUM, 0ull, pe_number);
> +
> +	p->mbt_cache[1][0] = IODA3_MBT0_ENABLE |
> +			     IODA3_MBT0_TYPE_M64 |
> +		SETFIELD(IODA3_MBT0_MODE, 0ull, IODA3_MBT0_MODE_SINGLE_PE) |
> +		SETFIELD(IODA3_MBT0_MDT_COLUMN, 0ull, 0) |
> +		(0x0002000000000000ULL & IODA3_MBT0_BASE_ADDR);
> +	p->mbt_cache[1][1] = IODA3_MBT1_ENABLE |
> +		(0x00ff000000000000ULL & IODA3_MBT1_MASK) |
> +		SETFIELD(IODA3_MBT1_SINGLE_PE_NUM, 0ull, pe_number);
> +
> +	phb4_ioda_sel(p, IODA3_TBL_MBT, 0, true);
> +	for (i = 0; i < p->mbt_size; i++) {
> +		out_be64(p->regs + PHB_IODA_DATA0, p->mbt_cache[i][0]);
> +		out_be64(p->regs + PHB_IODA_DATA0, p->mbt_cache[i][1]);
> +	}
> +
> +	phb4_init_capp_errors(p);
> +
> +	phb4_init_capp_regs(p);
> +
> +	if (!chiptod_capp_timebase_sync(p->chip_id, CAPP_TFMR,
> +					CAPP_TB,
> +					PHB4_CAPP_REG_OFFSET(p))) {
> +		PHBERR(p, "CAPP: Failed to sync timebase\n");
> +		return OPAL_HARDWARE;
> +	}
> +	return OPAL_SUCCESS;
> +}
> +
> +static int64_t phb4_set_capi_mode(struct phb *phb, uint64_t mode,
> +				  uint64_t pe_number)
> +{
> +	struct phb4 *p = phb_to_phb4(phb);
> +	struct proc_chip *chip = get_chip(p->chip_id);
> +	uint64_t reg;
> +	uint32_t offset;
> +
> +
> +	lock(&capi_lock);
> +	chip->capp_phb4_attached_mask |= 1 << p->index;
> +	unlock(&capi_lock);
> +
> +	offset = PHB4_CAPP_REG_OFFSET(p);
> +	xscom_read(p->chip_id, CAPP_ERR_STATUS_CTRL + offset, &reg);
> +	if ((reg & PPC_BIT(5))) {
> +		PHBERR(p, "CAPP: recovery failed (%016llx)\n", reg);
> +		return OPAL_HARDWARE;
> +	} else if ((reg & PPC_BIT(0)) && (!(reg & PPC_BIT(1)))) {
> +		PHBDBG(p, "CAPP: recovery in progress\n");
> +		return OPAL_BUSY;
> +	}
> +
> +	switch (mode) {
> +	case OPAL_PHB_CAPI_MODE_PCIE:
> +		return OPAL_UNSUPPORTED;
> +
> +	case OPAL_PHB_CAPI_MODE_CAPI:
> +		return enable_capi_mode(p, pe_number, CAPI_DMA_TVT0);
> +
> +	case OPAL_PHB_CAPI_MODE_DMA:
> +		/* shouldn't be called, enabled by default on p9 */
> +		return OPAL_UNSUPPORTED;
> +
> +	case OPAL_PHB_CAPI_MODE_DMA_TVT1:
> +		return enable_capi_mode(p, pe_number, CAPI_DMA_TVT1);
> +
> +	case OPAL_PHB_CAPI_MODE_SNOOP_OFF:
> +		/* shouldn't be called */
> +		return OPAL_UNSUPPORTED;
> +
> +	case OPAL_PHB_CAPI_MODE_SNOOP_ON:
> +		/* nothing to do */
> +		return OPAL_SUCCESS;
> +	}
> +
> +	return OPAL_UNSUPPORTED;
> +}
> +
>   static const struct phb_ops phb4_ops = {
>   	.cfg_read8		= phb4_pcicfg_read8,
>   	.cfg_read16		= phb4_pcicfg_read16,
> @@ -2541,6 +2886,7 @@ static const struct phb_ops phb4_ops = {
>   	.get_diag_data		= NULL,
>   	.get_diag_data2		= phb4_get_diag_data,
>   	.tce_kill		= phb4_tce_kill,
> +	.set_capi_mode		= phb4_set_capi_mode,
>   };
> 
>   static void phb4_init_ioda3(struct phb4 *p)
> @@ -2572,13 +2918,13 @@ static void phb4_init_ioda3(struct phb4 *p)
>   		 p->tbl_pest | PHB_PEST_BAR_ENABLE);
> 
>   	/* Init_23 - CRW Base Address Reg */
> -	// XXX FIXME learn CAPI :-(
> +	/* See enable_capi_mode() */
> 
>   	/* Init_24 - ASN Compare/Mask */
> -	// XXX FIXME learn CAPI :-(
> +	/* See enable_capi_mode() */
> 
>   	/* Init_25 - CAPI Compare/Mask */
> -	// XXX FIXME learn CAPI :-(
> +	/* See enable_capi_mode() */
> 
>   	/* Init_26 - PCIE Outbound upper address */
>   	out_be64(p->regs + PHB_M64_UPPER_BITS, 0);
> @@ -2883,7 +3229,7 @@ static void phb4_init_hw(struct phb4 *p, bool first_init)
>   	 */
> 
>   	/* Init_123 :  NBW. XXX TODO */
> -	// XXX FIXME learn CAPI :-(
> +	/* See enable_capi_mode() */
> 
>   	/* Init_124 : Setup PCI command/status on root complex
>   	 * I don't know why the spec does this now and not earlier, so
> @@ -3104,6 +3450,9 @@ static void phb4_add_properties(struct phb4 *p)
> 
>   	dt_add_property_cells(np, "ibm,phb-diag-data-size",
>   			      sizeof(struct OpalIoPhb4ErrorData));
> +
> +	/* Indicate to Linux that CAPP timebase sync is supported */
> +	dt_add_property_string(np, "ibm,capp-timebase-sync", NULL);
>   }
> 
>   static bool phb4_calculate_windows(struct phb4 *p)
> diff --git a/include/chip.h b/include/chip.h
> index b957e45..17f062b 100644
> --- a/include/chip.h
> +++ b/include/chip.h
> @@ -191,6 +191,7 @@ struct proc_chip {
> 
>   	/* Must hold capi_lock to change */
>   	uint8_t			capp_phb3_attached_mask;
> +	uint8_t			capp_phb4_attached_mask;
>   	uint8_t			capp_ucode_loaded;
> 
>   	/* Used by hw/centaur.c */
> diff --git a/include/opal-api.h b/include/opal-api.h
> index 37af5f7..2713490 100644
> --- a/include/opal-api.h
> +++ b/include/opal-api.h
> @@ -1144,6 +1144,7 @@ enum {
>   	OPAL_PHB_CAPI_MODE_SNOOP_OFF    = 2,
>   	OPAL_PHB_CAPI_MODE_SNOOP_ON	= 3,
>   	OPAL_PHB_CAPI_MODE_DMA		= 4,
> +	OPAL_PHB_CAPI_MODE_DMA_TVT1	= 5,
>   };
> 
>   /* CAPI feature flags (in device-tree) */
> diff --git a/include/phb4-capp.h b/include/phb4-capp.h
> new file mode 100644
> index 0000000..89de034
> --- /dev/null
> +++ b/include/phb4-capp.h
> @@ -0,0 +1,60 @@
> +/* Copyright 2013-2017 IBM Corp.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + *	http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> + * implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#ifndef __PHB4_CAPP_H
> +#define __PHB4_CAPP_H
> +
> +#define CAPP_SNP_ARRAY_WRITE_REG		0x2010841  /* Satellite 2 */
> +#define CAPP_SNP_ARRAY_ADDR_REG			0x2010828
> +#define CAPP_APC_MASTER_ARRAY_ADDR_REG		0x201082A
> +#define CAPP_APC_MASTER_ARRAY_WRITE_REG		0x2010842  /* Satellite 2 */
> +
> +#define CAPP_FIR				0x2010800
> +#define CAPP_ERR_RPT_CLR			0x2010813
> +#define APC_MASTER_PB_CTRL			0x2010818
> +#define APC_MASTER_CAPI_CTRL			0x2010819
> +#define LCO_MASTER_TARGET			0x2010821
> +#define EPOCH_RECOVERY_TIMERS_CTRL		0x201082C
> +#define SNOOP_CAPI_CONFIG			0x201081A
> +#define SNOOP_CONTROL				0x201081B
> +#define TRANSPORT_CONTROL			0x201081C
> +#define CAPP_TB					0x2010826
> +#define CAPP_TFMR				0x2010827
> +#define CAPP_ERR_STATUS_CTRL			0x201080E
> +#define FLUSH_SUE_STATE_MAP			0x201080F
> +#define FLUSH_CPIG_STATE_MAP			0x2010820
> +#define FLUSH_SUE_UOP1				0x2010843  /* Satellite 2 */
> +#define APC_FSM_READ_MASK			0x2010823
> +#define XPT_FSM_RMM				0x2010831
> +
> +/* CAPP0 attached to PHB0(PEC0 - single port)
> + * CAPP1 attached to PHB3(PEC2 - single or dual port)
> + */
> +#define CAPP0_PHB_INDEX 0
> +#define CAPP1_PHB_INDEX 3
> +
> +/* SCOM address Base (Ring = ‘0010’b)
> + * CAPP Unit Satellite           SCOM address Base
> + * CAPP 0    S1 (sat = ‘0000’b)  x02010800
> + * CAPP 0    S2 (sat = ‘0001’b)  x02010840
> + * CAPP 1    S1 (sat = ‘0000’b)  x04010800
> + * CAPP 1    S2 (sat = ‘0001’b)  x04010840
> + */
> +#define CAPP1_REG_OFFSET 0x2000000
> +
> +#define PHB4_CAPP_REG_OFFSET(p) ((p)->index == 0 ? 0x0 : CAPP1_REG_OFFSET)
> +
> +#endif /* __PHB4_CAPP_H */
> diff --git a/include/phb4-regs.h b/include/phb4-regs.h
> index 92bee88..5ec47a5 100644
> --- a/include/phb4-regs.h
> +++ b/include/phb4-regs.h
> @@ -71,8 +71,12 @@
>   #define PHB_PEST_BAR			0x1a8
>   #define   PHB_PEST_BAR_ENABLE		PPC_BIT(0)
>   #define   PHB_PEST_BASE_ADDRESS		PPC_BITMASK(8,51)
> +#define PHB_PBL_ASN_CMPM		0x1C0
> +#define   PHB_PBL_ASN_ENABLE		PPC_BIT(63)
> +#define PHB_CAPI_CMPM			0x1C8
> +#define   PHB_CAPI_CMPM_ENABLE		PPC_BIT(63)
>   #define PHB_M64_UPPER_BITS		0x1f0
> -#define PHB_INTREP_TIMER		0x1f8
> +#define PHB_NXLATE_PREFIX		0x1f8
>   #define PHB_DMARD_SYNC			0x200
>   #define   PHB_DMARD_SYNC_START		PPC_BIT(0)
>   #define   PHB_DMARD_SYNC_COMPLETE	PPC_BIT(1)
> @@ -242,6 +246,7 @@
>   #define PHB_PBL_TIMEOUT_CTRL			0x1810
>   #define PHB_PBL_NPTAG_ENABLE			0x1820
>   #define PHB_PBL_NBW_CMP_MASK			0x1830
> +#define   PHB_PBL_NBW_MASK_ENABLE		PPC_BIT(63)
>   #define PHB_PBL_SYS_LINK_INIT			0x1838
>   #define PHB_PBL_BUF_STATUS			0x1840
>   #define PHB_PBL_ERR_STATUS			0x1900
>
diff mbox

Patch

diff --git a/hw/phb4.c b/hw/phb4.c
index 3843456..5ea6138 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -47,7 +47,7 @@ 
 #include <affinity.h>
 #include <phb4.h>
 #include <phb4-regs.h>
-#include <capp.h>
+#include <phb4-capp.h>
 #include <fsp.h>
 #include <chip.h>
 #include <chiptod.h>
@@ -77,6 +77,11 @@  static void phb4_init_hw(struct phb4 *p, bool first_init);
 #define PHBLOGCFG(p, fmt, a...) do {} while (0)
 #endif
 
+enum capi_dma_tvt {
+	CAPI_DMA_TVT0,
+	CAPI_DMA_TVT1,
+};
+
 /* Note: The "ASB" name is historical, practically this means access via
  * the XSCOM backdoor
  */
@@ -2111,6 +2116,8 @@  static int64_t phb4_freset(struct pci_slot *slot)
 	return OPAL_HARDWARE;
 }
 
+extern struct lock capi_lock;
+
 static int64_t phb4_creset(struct pci_slot *slot)
 {
 	struct phb4 *p = phb_to_phb4(slot->phb);
@@ -2509,6 +2516,344 @@  static int64_t phb4_get_diag_data(struct phb *phb,
 	return OPAL_SUCCESS;
 }
 
+static uint64_t tve_encode_50b_noxlate(uint64_t start_addr, uint64_t end_addr)
+{
+	uint64_t tve;
+
+	/*
+	 * Put start address bits 49:24 into TVE[52:53]||[0:23]
+	 * and end address bits 49:24 into TVE[54:55]||[24:47]
+	 * and set TVE[51]
+	 */
+	tve  = (start_addr << 16) & (0xffffffull << 40);
+	tve |= (start_addr >> 38) & (3ull << 10);
+	tve |= (end_addr >>  8) & (0xfffffful << 16);
+	tve |= (end_addr >> 40) & (3ull << 8);
+	tve |= PPC_BIT(51) | IODA3_TVT_NON_TRANSLATE_50;
+	return tve;
+}
+
+static void phb4_init_capp_regs(struct phb4 *p)
+{
+	uint64_t reg;
+	uint32_t offset;
+
+	offset = PHB4_CAPP_REG_OFFSET(p);
+
+	/* Enable cresp examination by CAPP */
+	xscom_read(p->chip_id, APC_MASTER_PB_CTRL + offset, &reg);
+	reg |= PPC_BIT(0);
+	if (p->rev == PHB4_REV_NIMBUS_DD10) {
+		reg |= PPC_BIT(1);
+		/* disable vg not sys */
+		reg |= PPC_BIT(3);
+	}
+	xscom_write(p->chip_id, APC_MASTER_PB_CTRL + offset, reg);
+
+	/* Set PHB mode, HPC Dir State and P9 mode */
+	xscom_write(p->chip_id, APC_MASTER_CAPI_CTRL + offset,
+		    0x1772000000000000);
+	PHBINF(p, "CAPP: port attached\n");
+
+	/* Set snoop ttype decoding , dir size to 256k */
+	xscom_write(p->chip_id, SNOOP_CAPI_CONFIG + offset, 0xA000000000000000);
+
+	/* Use Read Epsilon Tier2 for all scopes, Address Pipeline Master
+	 * Wait Count to highest(1023) and Number of rpt_hang.data to 3
+	 */
+	xscom_write(p->chip_id, SNOOP_CONTROL + offset, 0x8000000010072000);
+
+	/* TLBI Hang Divider = 16.  CI Store Buffer Threshold initialized
+	 * to b’0101’ = use 6 buffers. X16 PCIe(14 buffers)
+	 */
+	xscom_read(p->chip_id, TRANSPORT_CONTROL + offset, &reg);
+	if (!(reg & PPC_BIT(4))) {
+		if (p->index == CAPP0_PHB_INDEX)
+			xscom_write(p->chip_id, TRANSPORT_CONTROL + offset,
+				    0x081400000000000A);
+
+		if (p->index == CAPP1_PHB_INDEX)
+			xscom_write(p->chip_id, TRANSPORT_CONTROL + offset,
+				    0x0814000000000008);
+
+		/* Initialize CI Store Buffers */
+		xscom_read(p->chip_id, TRANSPORT_CONTROL + offset, &reg);
+		reg |= PPC_BIT(63);
+		xscom_write(p->chip_id, TRANSPORT_CONTROL + offset, reg);
+	}
+
+	/* Enable epoch timer */
+	xscom_write(p->chip_id, EPOCH_RECOVERY_TIMERS_CTRL + offset,
+		    0xC0000000FFF0FFFE);
+
+	xscom_write(p->chip_id, FLUSH_SUE_STATE_MAP + offset,
+		    0x1DCF5F6600000000);
+	xscom_write(p->chip_id, FLUSH_SUE_UOP1 + offset, 0xE310280428000000);
+
+	/* capp owns PHB read buffers */
+	if (p->index == CAPP0_PHB_INDEX) {
+		xscom_write(p->chip_id, APC_FSM_READ_MASK + offset,
+			    0xFFFFFFFFFFFF0000);
+		xscom_write(p->chip_id, XPT_FSM_RMM + offset,
+			    0xFFFFFFFFFFFF0000);
+	}
+	if (p->index == CAPP1_PHB_INDEX) {
+		xscom_write(p->chip_id, APC_FSM_READ_MASK + offset,
+			    0xFFFFFFFE00000000);
+		xscom_write(p->chip_id, XPT_FSM_RMM + offset,
+			    0xFFFFFFFE00000000);
+	}
+
+	/* Deassert TLBI_FENCED and tlbi_psl_is_dead */
+	xscom_write(p->chip_id, CAPP_ERR_STATUS_CTRL + offset, 0);
+}
+
+/* override some inits with CAPI defaults */
+static void phb4_init_capp_errors(struct phb4 *p)
+{
+	/* Init_77: TXE Error AIB Fence Enable Register */
+	out_be64(p->regs + 0x0d30,	0xdff7ff0bf7ddfff0ull);
+
+	/* Init_86: RXE_ARB Error AIB Fence Enable Register */
+	out_be64(p->regs + 0x0db0,	0xfbffd7bbff7fbfefull);
+
+	/* Init_95: RXE_MRG Error AIB Fence Enable Register */
+	out_be64(p->regs + 0x0e30,	0xfffffeffff7fff57ull);
+
+	/* Init_104: RXE_TCE Error AIB Fence Enable Register */
+	out_be64(p->regs + 0x0eb0,	0xffaeffafffffffffull);
+
+	/* Init_113: PHB Error AIB Fence Enable Register */
+	out_be64(p->regs + 0x0cb0,	0x35777073ff000000ull);
+}
+
+/* Power Bus Common Queue Registers
+ * All PBCQ and PBAIB registers are accessed via SCOM
+ * NestBase = 4010C00 for PEC0
+ *            4011000 for PEC1
+ *            4011400 for PEC2
+ *
+ * Some registers are shared amongst all of the stacks and will only
+ * have 1 copy. Other registers are implemented one per stack.
+ * Registers that are duplicated will have an additional offset
+ * of “StackBase” so that they have a unique address.
+ * Stackoffset = 00000040 for Stack0
+ *             = 00000080 for Stack1
+ *             = 000000C0 for Stack2
+ */
+static int64_t enable_capi_mode(struct phb4 *p, uint64_t pe_number,
+				enum capi_dma_tvt dma_tvt)
+{
+	uint64_t reg, start_addr, end_addr;
+	uint32_t offset;
+	int i;
+
+	xscom_read(p->chip_id, p->pe_xscom + 0x7, &reg);
+	if (reg & PPC_BIT(0))
+		PHBDBG(p, "Already in CAPP mode\n");
+
+	/* PEC Phase 3 (PBCQ) registers Init */
+	/* poll cqstat
+	 * CAPP0 attached to PHB0(PEC0)
+	 * CAPP1 attached to PHB3(PEC2)
+	 */
+	if (p->index == 0) {
+		/* PEC 0 */
+		offset = 0x40;
+	} else if (p->index == 1 || p->index == 2) {
+		/* PEC 1 */
+		offset = 0x80;
+	} else {
+		/* PEC 2 */
+		offset = 0xC0;
+	}
+
+	for (i = 0; i < 500000; i++) {
+		xscom_read(p->chip_id, p->pe_xscom + offset + 0xC, &reg);
+		if (!(reg & 0xC000000000000000))
+			break;
+		time_wait_us(10);
+	}
+	if (reg & 0xC000000000000000) {
+		PHBERR(p, "CAPP: Timeout waiting for pending transaction\n");
+		return OPAL_HARDWARE;
+	}
+
+	/* Enable CAPP Mode , Set 14 CI Store buffers for CAPP,
+	 * Set 48 Read machines for CAPP.
+	 */
+	if (p->index == CAPP0_PHB_INDEX)
+		reg = 0x800EFFFFFFFFFFFF;
+
+	if (p->index == CAPP1_PHB_INDEX)
+		reg = 0x8006FFFFFFFE0000;
+	xscom_write(p->chip_id, p->pe_xscom + 0x7, reg);
+
+	if (p->rev == PHB4_REV_NIMBUS_DD10) {
+		/* Ignores the PB init signal */
+		xscom_read(p->chip_id, p->pe_xscom + 0x0, &reg);
+		reg |= PPC_BIT(12);
+		xscom_write(p->chip_id, p->pe_xscom + 0x0, reg);
+	}
+
+	/* PEC Phase 4 (PHB) registers adjustment
+	 * Bit [0:7] XSL_DSNCTL[capiind]
+	 * Init_25 - CAPI Compare/Mask
+	 */
+	out_be64(p->regs + PHB_CAPI_CMPM,
+		 0x0200FE0000000000Ull | PHB_CAPI_CMPM_ENABLE);
+
+	if (!(p->rev == PHB4_REV_NIMBUS_DD10)) {
+		/* Init_123 :  NBW Compare/Mask Register */
+		out_be64(p->regs + PHB_PBL_NBW_CMP_MASK,
+			 0x0300FF0000000000Ull | PHB_PBL_NBW_MASK_ENABLE);
+
+		/* Init_24 - ASN Compare/Mask */
+		out_be64(p->regs + PHB_PBL_ASN_CMPM,
+			 0x0400FF0000000000Ull | PHB_PBL_ASN_ENABLE);
+	}
+
+	/* non-translate/50-bit mode */
+	out_be64(p->regs + PHB_NXLATE_PREFIX, 0x0000000000000000Ull);
+
+	/* set tve no translate mode allow mmio window */
+	memset(p->tve_cache, 0x0, sizeof(p->tve_cache));
+
+	/*
+	 * In 50-bit non-translate mode, the fields of the TVE are
+	 * used to perform an address range check. In this mode TCE
+	 * Table Size(0) must be a '1' (TVE[51] = 1)
+	 *      PCI Addr(49:24) >= TVE[52:53]+TVE[0:23] and
+	 *      PCI Addr(49:24) < TVE[54:55]+TVE[24:47]
+	 *
+	 * TVE[51] = 1
+	 * TVE[56] = 1: 50-bit Non-Translate Mode Enable
+	 * TVE[0:23] = 0x000000
+	 * TVE[24:47] = 0xFFFFFF
+	 *
+	 * capi dma mode: CAPP DMA mode needs access to all of memory
+	 * capi mode: Allow address range (bit 14 = 1)
+	 *            0x0002000000000000: 0x0002FFFFFFFFFFFF
+	 *            TVE[52:53] = '10' and TVE[54:55] = '10'
+	 */
+
+	/* TVT#0: CAPI window + DMA, all memory */
+	start_addr = 0ull;
+	end_addr   = 0x0003ffffffffffffull;
+	p->tve_cache[pe_number * 2] =
+		tve_encode_50b_noxlate(start_addr, end_addr);
+
+	/* TVT#1: DMA, all memory, in bypass mode */
+	if (dma_tvt == CAPI_DMA_TVT1) {
+		start_addr = (1ull << 59);
+		end_addr   = start_addr + 0x0003ffffffffffffull;
+		p->tve_cache[pe_number * 2 + 1] =
+			tve_encode_50b_noxlate(start_addr, end_addr);
+	}
+
+	phb4_ioda_sel(p, IODA3_TBL_TVT, 0, true);
+	for (i = 0; i < p->tvt_size; i++)
+		out_be64(p->regs + PHB_IODA_DATA0, p->tve_cache[i]);
+
+	/* set mbt bar to pass capi mmio window. First applied cleared
+	 * values to HW
+	 */
+	for (i = 0; i < p->mbt_size; i++) {
+		p->mbt_cache[i][0] = 0;
+		p->mbt_cache[i][1] = 0;
+	}
+	phb4_ioda_sel(p, IODA3_TBL_MBT, 0, true);
+	for (i = 0; i < p->mbt_size; i++) {
+		out_be64(p->regs + PHB_IODA_DATA0, p->mbt_cache[i][0]);
+		out_be64(p->regs + PHB_IODA_DATA0, p->mbt_cache[i][1]);
+	}
+
+	p->mbt_cache[0][0] = IODA3_MBT0_ENABLE |
+			     IODA3_MBT0_TYPE_M64 |
+		SETFIELD(IODA3_MBT0_MODE, 0ull, IODA3_MBT0_MODE_SINGLE_PE) |
+		SETFIELD(IODA3_MBT0_MDT_COLUMN, 0ull, 0) |
+		(p->mm0_base & IODA3_MBT0_BASE_ADDR);
+	p->mbt_cache[0][1] = IODA3_MBT1_ENABLE |
+		((~(p->mm0_size - 1)) & IODA3_MBT1_MASK) |
+		SETFIELD(IODA3_MBT1_SINGLE_PE_NUM, 0ull, pe_number);
+
+	p->mbt_cache[1][0] = IODA3_MBT0_ENABLE |
+			     IODA3_MBT0_TYPE_M64 |
+		SETFIELD(IODA3_MBT0_MODE, 0ull, IODA3_MBT0_MODE_SINGLE_PE) |
+		SETFIELD(IODA3_MBT0_MDT_COLUMN, 0ull, 0) |
+		(0x0002000000000000ULL & IODA3_MBT0_BASE_ADDR);
+	p->mbt_cache[1][1] = IODA3_MBT1_ENABLE |
+		(0x00ff000000000000ULL & IODA3_MBT1_MASK) |
+		SETFIELD(IODA3_MBT1_SINGLE_PE_NUM, 0ull, pe_number);
+
+	phb4_ioda_sel(p, IODA3_TBL_MBT, 0, true);
+	for (i = 0; i < p->mbt_size; i++) {
+		out_be64(p->regs + PHB_IODA_DATA0, p->mbt_cache[i][0]);
+		out_be64(p->regs + PHB_IODA_DATA0, p->mbt_cache[i][1]);
+	}
+
+	phb4_init_capp_errors(p);
+
+	phb4_init_capp_regs(p);
+
+	if (!chiptod_capp_timebase_sync(p->chip_id, CAPP_TFMR,
+					CAPP_TB,
+					PHB4_CAPP_REG_OFFSET(p))) {
+		PHBERR(p, "CAPP: Failed to sync timebase\n");
+		return OPAL_HARDWARE;
+	}
+	return OPAL_SUCCESS;
+}
+
+static int64_t phb4_set_capi_mode(struct phb *phb, uint64_t mode,
+				  uint64_t pe_number)
+{
+	struct phb4 *p = phb_to_phb4(phb);
+	struct proc_chip *chip = get_chip(p->chip_id);
+	uint64_t reg;
+	uint32_t offset;
+
+
+	lock(&capi_lock);
+	chip->capp_phb4_attached_mask |= 1 << p->index;
+	unlock(&capi_lock);
+
+	offset = PHB4_CAPP_REG_OFFSET(p);
+	xscom_read(p->chip_id, CAPP_ERR_STATUS_CTRL + offset, &reg);
+	if ((reg & PPC_BIT(5))) {
+		PHBERR(p, "CAPP: recovery failed (%016llx)\n", reg);
+		return OPAL_HARDWARE;
+	} else if ((reg & PPC_BIT(0)) && (!(reg & PPC_BIT(1)))) {
+		PHBDBG(p, "CAPP: recovery in progress\n");
+		return OPAL_BUSY;
+	}
+
+	switch (mode) {
+	case OPAL_PHB_CAPI_MODE_PCIE:
+		return OPAL_UNSUPPORTED;
+
+	case OPAL_PHB_CAPI_MODE_CAPI:
+		return enable_capi_mode(p, pe_number, CAPI_DMA_TVT0);
+
+	case OPAL_PHB_CAPI_MODE_DMA:
+		/* shouldn't be called, enabled by default on p9 */
+		return OPAL_UNSUPPORTED;
+
+	case OPAL_PHB_CAPI_MODE_DMA_TVT1:
+		return enable_capi_mode(p, pe_number, CAPI_DMA_TVT1);
+
+	case OPAL_PHB_CAPI_MODE_SNOOP_OFF:
+		/* shouldn't be called */
+		return OPAL_UNSUPPORTED;
+
+	case OPAL_PHB_CAPI_MODE_SNOOP_ON:
+		/* nothing to do */
+		return OPAL_SUCCESS;
+	}
+
+	return OPAL_UNSUPPORTED;
+}
+
 static const struct phb_ops phb4_ops = {
 	.cfg_read8		= phb4_pcicfg_read8,
 	.cfg_read16		= phb4_pcicfg_read16,
@@ -2541,6 +2886,7 @@  static const struct phb_ops phb4_ops = {
 	.get_diag_data		= NULL,
 	.get_diag_data2		= phb4_get_diag_data,
 	.tce_kill		= phb4_tce_kill,
+	.set_capi_mode		= phb4_set_capi_mode,
 };
 
 static void phb4_init_ioda3(struct phb4 *p)
@@ -2572,13 +2918,13 @@  static void phb4_init_ioda3(struct phb4 *p)
 		 p->tbl_pest | PHB_PEST_BAR_ENABLE);
 
 	/* Init_23 - CRW Base Address Reg */
-	// XXX FIXME learn CAPI :-(
+	/* See enable_capi_mode() */
 
 	/* Init_24 - ASN Compare/Mask */
-	// XXX FIXME learn CAPI :-(
+	/* See enable_capi_mode() */
 
 	/* Init_25 - CAPI Compare/Mask */
-	// XXX FIXME learn CAPI :-(
+	/* See enable_capi_mode() */
 
 	/* Init_26 - PCIE Outbound upper address */
 	out_be64(p->regs + PHB_M64_UPPER_BITS, 0);
@@ -2883,7 +3229,7 @@  static void phb4_init_hw(struct phb4 *p, bool first_init)
 	 */
 
 	/* Init_123 :  NBW. XXX TODO */
-	// XXX FIXME learn CAPI :-(
+	/* See enable_capi_mode() */
 
 	/* Init_124 : Setup PCI command/status on root complex
 	 * I don't know why the spec does this now and not earlier, so
@@ -3104,6 +3450,9 @@  static void phb4_add_properties(struct phb4 *p)
 
 	dt_add_property_cells(np, "ibm,phb-diag-data-size",
 			      sizeof(struct OpalIoPhb4ErrorData));
+
+	/* Indicate to Linux that CAPP timebase sync is supported */
+	dt_add_property_string(np, "ibm,capp-timebase-sync", NULL);
 }
 
 static bool phb4_calculate_windows(struct phb4 *p)
diff --git a/include/chip.h b/include/chip.h
index b957e45..17f062b 100644
--- a/include/chip.h
+++ b/include/chip.h
@@ -191,6 +191,7 @@  struct proc_chip {
 
 	/* Must hold capi_lock to change */
 	uint8_t			capp_phb3_attached_mask;
+	uint8_t			capp_phb4_attached_mask;
 	uint8_t			capp_ucode_loaded;
 
 	/* Used by hw/centaur.c */
diff --git a/include/opal-api.h b/include/opal-api.h
index 37af5f7..2713490 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -1144,6 +1144,7 @@  enum {
 	OPAL_PHB_CAPI_MODE_SNOOP_OFF    = 2,
 	OPAL_PHB_CAPI_MODE_SNOOP_ON	= 3,
 	OPAL_PHB_CAPI_MODE_DMA		= 4,
+	OPAL_PHB_CAPI_MODE_DMA_TVT1	= 5,
 };
 
 /* CAPI feature flags (in device-tree) */
diff --git a/include/phb4-capp.h b/include/phb4-capp.h
new file mode 100644
index 0000000..89de034
--- /dev/null
+++ b/include/phb4-capp.h
@@ -0,0 +1,60 @@ 
+/* Copyright 2013-2017 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PHB4_CAPP_H
+#define __PHB4_CAPP_H
+
+#define CAPP_SNP_ARRAY_WRITE_REG		0x2010841  /* Satellite 2 */
+#define CAPP_SNP_ARRAY_ADDR_REG			0x2010828
+#define CAPP_APC_MASTER_ARRAY_ADDR_REG		0x201082A
+#define CAPP_APC_MASTER_ARRAY_WRITE_REG		0x2010842  /* Satellite 2 */
+
+#define CAPP_FIR				0x2010800
+#define CAPP_ERR_RPT_CLR			0x2010813
+#define APC_MASTER_PB_CTRL			0x2010818
+#define APC_MASTER_CAPI_CTRL			0x2010819
+#define LCO_MASTER_TARGET			0x2010821
+#define EPOCH_RECOVERY_TIMERS_CTRL		0x201082C
+#define SNOOP_CAPI_CONFIG			0x201081A
+#define SNOOP_CONTROL				0x201081B
+#define TRANSPORT_CONTROL			0x201081C
+#define CAPP_TB					0x2010826
+#define CAPP_TFMR				0x2010827
+#define CAPP_ERR_STATUS_CTRL			0x201080E
+#define FLUSH_SUE_STATE_MAP			0x201080F
+#define FLUSH_CPIG_STATE_MAP			0x2010820
+#define FLUSH_SUE_UOP1				0x2010843  /* Satellite 2 */
+#define APC_FSM_READ_MASK			0x2010823
+#define XPT_FSM_RMM				0x2010831
+
+/* CAPP0 attached to PHB0(PEC0 - single port)
+ * CAPP1 attached to PHB3(PEC2 - single or dual port)
+ */
+#define CAPP0_PHB_INDEX 0
+#define CAPP1_PHB_INDEX 3
+
+/* SCOM address Base (Ring = ‘0010’b)
+ * CAPP Unit Satellite           SCOM address Base
+ * CAPP 0    S1 (sat = ‘0000’b)  x02010800
+ * CAPP 0    S2 (sat = ‘0001’b)  x02010840
+ * CAPP 1    S1 (sat = ‘0000’b)  x04010800
+ * CAPP 1    S2 (sat = ‘0001’b)  x04010840
+ */
+#define CAPP1_REG_OFFSET 0x2000000
+
+#define PHB4_CAPP_REG_OFFSET(p) ((p)->index == 0 ? 0x0 : CAPP1_REG_OFFSET)
+
+#endif /* __PHB4_CAPP_H */
diff --git a/include/phb4-regs.h b/include/phb4-regs.h
index 92bee88..5ec47a5 100644
--- a/include/phb4-regs.h
+++ b/include/phb4-regs.h
@@ -71,8 +71,12 @@ 
 #define PHB_PEST_BAR			0x1a8
 #define   PHB_PEST_BAR_ENABLE		PPC_BIT(0)
 #define   PHB_PEST_BASE_ADDRESS		PPC_BITMASK(8,51)
+#define PHB_PBL_ASN_CMPM		0x1C0
+#define   PHB_PBL_ASN_ENABLE		PPC_BIT(63)
+#define PHB_CAPI_CMPM			0x1C8
+#define   PHB_CAPI_CMPM_ENABLE		PPC_BIT(63)
 #define PHB_M64_UPPER_BITS		0x1f0
-#define PHB_INTREP_TIMER		0x1f8
+#define PHB_NXLATE_PREFIX		0x1f8
 #define PHB_DMARD_SYNC			0x200
 #define   PHB_DMARD_SYNC_START		PPC_BIT(0)
 #define   PHB_DMARD_SYNC_COMPLETE	PPC_BIT(1)
@@ -242,6 +246,7 @@ 
 #define PHB_PBL_TIMEOUT_CTRL			0x1810
 #define PHB_PBL_NPTAG_ENABLE			0x1820
 #define PHB_PBL_NBW_CMP_MASK			0x1830
+#define   PHB_PBL_NBW_MASK_ENABLE		PPC_BIT(63)
 #define PHB_PBL_SYS_LINK_INIT			0x1838
 #define PHB_PBL_BUF_STATUS			0x1840
 #define PHB_PBL_ERR_STATUS			0x1900