blob: be9f4cbbb98e61d56a5d0ecac10b1d09dae74979 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
/* Copyright 2013-2018 IBM Corp. */
#ifndef __PHB3_H
#define __PHB3_H
#include <interrupts.h>
/*
* Memory map
*
* In addition to the 4K MMIO registers window, the PBCQ will
* forward down one or two large MMIO regions for use by the
* PHB.
*
* We try to use the largest MMIO window for the M64 space and
* the smallest for the M32 space, but we require at least 2G
* of M32, otherwise we carve it out of M64.
*/
#define M32_PCI_START 0x080000000 /* Offset of the actual M32 window in PCI */
#define M32_PCI_SIZE 0x80000000ul /* Size for M32 */
/*
* Interrupt map.
*
* Each PHB supports 2K interrupt sources, which is shared by
* LSI and MSI. With default configuration, MSI would use range
* [0, 0x7f7] and LSI would use [0x7f8, 0x7ff]. The interrupt
* source should be combined with IRSN to form final hardware
* IRQ.
*/
#define PHB3_MSI_IRQ_MIN 0x000
#define PHB3_MSI_IRQ_COUNT 0x7F8
#define PHB3_MSI_IRQ_MAX (PHB3_MSI_IRQ_MIN+PHB3_MSI_IRQ_COUNT-1)
#define PHB3_LSI_IRQ_MIN (PHB3_MSI_IRQ_COUNT)
#define PHB3_LSI_IRQ_COUNT 8
#define PHB3_LSI_IRQ_MAX (PHB3_LSI_IRQ_MIN+PHB3_LSI_IRQ_COUNT-1)
#define PHB3_MSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(chip, phb) | \
PHB3_MSI_IRQ_MIN)
#define PHB3_LSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(chip, phb) | \
PHB3_LSI_IRQ_MIN)
#define PHB3_IRQ_NUM(irq) (irq & 0x7FF)
/*
* LSI interrupts
*
* The LSI interrupt block supports 8 interrupts. 4 of them are the
* standard PCIe INTA..INTB. The rest is for additional functions
* of the PHB
*/
#define PHB3_LSI_PCIE_INTA 0
#define PHB3_LSI_PCIE_INTB 1
#define PHB3_LSI_PCIE_INTC 2
#define PHB3_LSI_PCIE_INTD 3
#define PHB3_LSI_PCIE_INF 6
#define PHB3_LSI_PCIE_ER 7
/*
* In-memory tables
*
* PHB3 requires a bunch of tables to be in memory instead of
* arrays inside the chip (unlike previous versions of the
* design).
*
* Some of them (IVT, etc...) will be provided by the OS via an
* OPAL call, not only not all of them, we also need to make sure
* some like PELT-V exist before we do our internal slot probing
* or bad thing would happen on error (the whole PHB would go into
* Fatal error state).
*
* So we maintain a set of tables internally for those mandatory
* ones within our core memory. They are fairly small. They can
* still be replaced by OS provided ones via OPAL APIs (and reset
* to the internal ones) so the OS can provide node local allocation
* for better performances.
*
* All those tables have to be naturally aligned
*/
/* RTT Table : 128KB - Maps RID to PE#
*
* Entries are 2 bytes indexed by PCIe RID
*/
#define RTT_TABLE_ENTRIES 0x10000
#define RTT_TABLE_SIZE 0x20000
/* IVT Table : MSI Interrupt vectors * state.
*
* We're sure that simics has 16-bytes IVE, totally 32KB.
* However the real HW possiblly has 128-bytes IVE, totally 256KB.
*/
#define IVT_TABLE_ENTRIES 0x800
/* Default to 128-bytes IVEs, uncomment that to force it back to 16-bytes */
//#define IVT_TABLE_IVE_16B
#ifdef IVT_TABLE_IVE_16B
#define IVT_TABLE_SIZE 0x8000
#define IVT_TABLE_STRIDE 2 /* double-words */
#else
#define IVT_TABLE_SIZE 0x40000
#define IVT_TABLE_STRIDE 16 /* double-words */
#endif
/* PELT-V Table : 8KB - Maps PE# to PE# dependencies
*
* 256 entries of 256 bits (32 bytes) each
*/
#define PELTV_TABLE_SIZE 0x2000
/* PEST Table : 4KB - PE state table
*
* 256 entries of 16 bytes each containing state bits for each PE
*
* AFAIK: This acts as a backup for an on-chip cache and shall be
* accessed via the indirect IODA table access registers only
*/
#define PEST_TABLE_SIZE 0x1000
/* RBA Table : 256 bytes - Reject Bit Array
*
* 2048 interrupts, 1 bit each, indiates the reject state of interrupts
* Not used (Murano / Venice DD1 only)
*/
#define RBA_TABLE_SIZE 0x100
/*
* Maximal supported PE# in PHB3. We probably probe it from EEH
* capability register later.
*/
#define PHB3_MAX_PE_NUM 256
#define PHB3_RESERVED_PE_NUM 255
/*
* PHB3 PCI slot state. When you're going to apply any
* changes here, please make sure the base state isn't
* conflicting with those defined in pci-slot.h
*/
#define PHB3_SLOT_NORMAL PCI_SLOT_STATE_NORMAL
#define PHB3_SLOT_LINK PCI_SLOT_STATE_LINK
#define PHB3_SLOT_LINK_START (PHB3_SLOT_LINK + 1)
#define PHB3_SLOT_LINK_WAIT_ELECTRICAL (PHB3_SLOT_LINK + 2)
#define PHB3_SLOT_LINK_WAIT (PHB3_SLOT_LINK + 3)
#define PHB3_SLOT_HRESET PCI_SLOT_STATE_HRESET
#define PHB3_SLOT_HRESET_START (PHB3_SLOT_HRESET + 1)
#define PHB3_SLOT_HRESET_DELAY (PHB3_SLOT_HRESET + 2)
#define PHB3_SLOT_HRESET_DELAY2 (PHB3_SLOT_HRESET + 3)
#define PHB3_SLOT_FRESET PCI_SLOT_STATE_FRESET
#define PHB3_SLOT_FRESET_START (PHB3_SLOT_FRESET + 1)
#define PHB3_SLOT_FRESET_ASSERT_DELAY (PHB3_SLOT_FRESET + 2)
#define PHB3_SLOT_FRESET_DEASSERT_DELAY (PHB3_SLOT_FRESET + 3)
#define PHB3_SLOT_CRESET PCI_SLOT_STATE_CRESET
#define PHB3_SLOT_CRESET_START (PHB3_SLOT_CRESET + 1)
#define PHB3_SLOT_CRESET_WAIT_CQ (PHB3_SLOT_CRESET + 2)
#define PHB3_SLOT_CRESET_REINIT (PHB3_SLOT_CRESET + 3)
#define PHB3_SLOT_CRESET_FRESET (PHB3_SLOT_CRESET + 4)
/*
* PHB3 error descriptor. Errors from all components (PBCQ, PHB)
* will be cached to PHB3 instance. However, PBCQ errors would
* have higher priority than those from PHB
*/
#define PHB3_ERR_SRC_NONE 0
#define PHB3_ERR_SRC_PBCQ 1
#define PHB3_ERR_SRC_PHB 2
#define PHB3_ERR_CLASS_NONE 0
#define PHB3_ERR_CLASS_DEAD 1
#define PHB3_ERR_CLASS_FENCED 2
#define PHB3_ERR_CLASS_ER 3
#define PHB3_ERR_CLASS_INF 4
#define PHB3_ERR_CLASS_LAST 5
struct phb3_err {
uint32_t err_src;
uint32_t err_class;
uint32_t err_bit;
};
/* Link timeouts, increments of 100ms */
#define PHB3_LINK_WAIT_RETRIES 20
#define PHB3_LINK_ELECTRICAL_RETRIES 20
/* PHB3 flags */
#define PHB3_AIB_FENCED (1 << 0)
#define PHB3_CFG_USE_ASB (1 << 1)
#define PHB3_CFG_BLOCKED (1 << 2)
#define PHB3_CAPP_RECOVERY (1 << 3)
#define PHB3_CAPP_DISABLING (1 << 4)
struct phb3 {
unsigned int index; /* 0..2 index inside P8 */
unsigned int flags;
unsigned int chip_id; /* Chip ID (== GCID on P8) */
bool broken;
unsigned int rev; /* 00MMmmmm */
#define PHB3_REV_MURANO_DD10 0xa30001
#define PHB3_REV_VENICE_DD10 0xa30002
#define PHB3_REV_MURANO_DD20 0xa30003
#define PHB3_REV_MURANO_DD21 0xa30004
#define PHB3_REV_VENICE_DD20 0xa30005
#define PHB3_REV_NAPLES_DD10 0xb30001
void *regs;
uint64_t pe_xscom; /* XSCOM bases */
uint64_t pci_xscom;
uint64_t spci_xscom;
uint64_t mm0_base; /* Full MM window to PHB */
uint64_t mm0_size; /* '' '' '' */
uint64_t mm1_base; /* Full MM window to PHB */
uint64_t mm1_size; /* '' '' '' */
uint32_t base_msi;
uint32_t base_lsi;
/* SkiBoot owned in-memory tables */
__be16 *tbl_rtt;
uint8_t *tbl_peltv;
__be64 *tbl_pest;
__be64 *tbl_ivt;
bool skip_perst; /* Skip first perst */
bool has_link;
int64_t ecap; /* cached PCI-E cap offset */
int64_t aercap; /* cached AER ecap offset */
const __be64 *lane_eq;
unsigned int max_link_speed;
uint32_t no_ecrc_devs;
__be16 rte_cache[RTT_TABLE_ENTRIES];
uint8_t peltv_cache[PELTV_TABLE_SIZE];
uint64_t lxive_cache[8];
__be64 ive_cache[IVT_TABLE_ENTRIES];
uint64_t tve_cache[512];
uint64_t m32d_cache[256];
uint64_t m64b_cache[16];
uint64_t nfir_cache; /* Used by complete reset */
bool err_pending;
struct phb3_err err;
struct phb phb;
};
#define PHB3_IS_NAPLES(p) ((p)->rev == PHB3_REV_NAPLES_DD10)
/*
* Venice/Murano have one CAPP unit, that can be attached to PHB0,1 or 2.
* Naples has two CAPP units: CAPP0 attached to PHB0, CAPP1 attached to PHB1.
*/
#define PHB3_CAPP_MAX_PHB_INDEX(p) (PHB3_IS_NAPLES(p) ? 1 : 2)
#define PHB3_CAPP_REG_OFFSET(p) \
((p)->index && PHB3_IS_NAPLES(p) ? CAPP1_REG_OFFSET : 0x0)
static inline struct phb3 *phb_to_phb3(struct phb *phb)
{
return container_of(phb, struct phb3, phb);
}
static inline uint64_t phb3_read_reg_asb(struct phb3 *p, uint64_t offset)
{
uint64_t val;
xscom_write(p->chip_id, p->spci_xscom, offset);
xscom_read(p->chip_id, p->spci_xscom + 0x2, &val);
return val;
}
static inline void phb3_write_reg_asb(struct phb3 *p,
uint64_t offset, uint64_t val)
{
xscom_write(p->chip_id, p->spci_xscom, offset);
xscom_write(p->chip_id, p->spci_xscom + 0x2, val);
}
static inline bool phb3_err_pending(struct phb3 *p)
{
return p->err_pending;
}
static inline void phb3_set_err_pending(struct phb3 *p, bool pending)
{
if (!pending) {
p->err.err_src = PHB3_ERR_SRC_NONE;
p->err.err_class = PHB3_ERR_CLASS_NONE;
p->err.err_bit = -1;
}
p->err_pending = pending;
}
#endif /* __PHB3_H */