diff options
Diffstat (limited to 'roms/skiboot/include/npu.h')
-rw-r--r-- | roms/skiboot/include/npu.h | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/roms/skiboot/include/npu.h b/roms/skiboot/include/npu.h new file mode 100644 index 000000000..50cc9c9fc --- /dev/null +++ b/roms/skiboot/include/npu.h @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* Copyright 2013-2017 IBM Corp. */ + +#ifndef __NPU_H +#define __NPU_H + +#include <io.h> + +/* Number of PEs supported */ +#define NPU_NUM_OF_PES 4 + +/* Each brick has 2 MMIO BARs at the maximum. BAR0 is always used to + * map the 128KB TL/DL registers. BAR1 is used to map either the PL or + * the AT registers which are not exposed to the OS. + */ +#define NPU_BRICK_NUM_OF_BARS 2 +#define NPU_BRICK_TL_BAR_SIZE 0x20000 +#define NPU_BRICK_PL_BAR_SIZE 0x200000 + +/* Bytes of the emulated NPU PCI device config space. We are + * emulating PCI express device, not legacy one + */ +#define NPU_DEV_CFG_SIZE 0x100 + +/* Interrupt mapping + * + * NPU PHB doesn't support MSI interrupts. It only supports + * 8 LSI interrupts: [0, 3] for bricks' DL blocks. [4, 5] + * for reporting errors from DL blocks. [6, 7] for reporting + * errors from TL blocks, NPCQs and AT. + */ +#define NPU_LSI_IRQ_COUNT 8 +#define NPU_LSI_INT_DL0 0 +#define NPU_LSI_INT_DL1 1 +#define NPU_LSI_INT_DL2 2 +#define NPU_LSI_INT_DL3 3 +#define NPU_LSI_IRQ_MIN 0x7F0 +#define NPU_LSI_IRQ_MAX (NPU_LSI_IRQ_MIN + NPU_LSI_IRQ_COUNT - 1) +#define NPU_LSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(chip, phb) | NPU_LSI_IRQ_MIN) +#define NPU_IRQ_NUM(irq) (irq & 0x7FF) + +/* NPU device capability descriptor. All PCI capabilities is + * organized as linked list. Each PCI capability has specific + * hook to populate when initializing NPU device. + */ +struct npu_dev; +struct npu_dev_cap { + uint16_t id; + uint16_t start; + uint16_t end; + struct npu_dev *dev; + void (*populate)(struct npu_dev_cap *cap); + struct list_node link; +}; + +struct npu_dev_bar { + uint32_t flags; + uint32_t xscom; + uint64_t base; + uint64_t size; + uint32_t bar_sz; + bool trapped; +}; + +/* Each device contains 2 links. The device will be exposed as + * standard PCIE device and the config space is emulated by skiboot. + */ +struct npu_dev { + uint32_t flags; + uint32_t index; + uint64_t xscom; + void *pl_base; + uint64_t pl_xscom_base; + struct npu_dev_bar bar; + struct phb *phb; + + /* The link@x node */ + struct dt_node *dt_node; + + /* PCI virtual device and the associated GPU device */ + struct pci_virt_device *pvd; + struct pci_device *pd; + struct npu *npu; + struct list_head capabilities; + + /* Which PHY lanes this device is associated with */ + uint16_t lane_mask; + + /* Used to store the currently running procedure number for + * this device. */ + uint16_t procedure_number; + + /* Used to store the step within a procedure that we are up + * to. */ + uint16_t procedure_step; + + /* Arbitrary data used by each procedure to track status. */ + uint64_t procedure_data; + + /* Used to timeout long running procedures. */ + unsigned long procedure_tb; + + uint32_t procedure_status; + + uint64_t pe_number; + + /* Used to associate the NPU device with GPU PCI devices */ + const char *slot_label; +}; + +/* NPU PHB descriptor */ +struct npu { + uint32_t flags; + uint32_t index; + uint32_t chip_id; + uint64_t xscom_base; + uint64_t at_xscom; + void *at_regs; + uint32_t base_lsi; + uint64_t mm_base; + uint64_t mm_size; + uint32_t total_devices; + struct npu_dev *devices; + + /* IODA cache */ + uint64_t lxive_cache[8]; + uint64_t pce_cache[6]; + uint64_t tve_cache[NPU_NUM_OF_PES]; + + bool tx_zcal_complete[2]; + bool fenced; + + struct phb phb; +}; + +static inline struct npu *phb_to_npu(struct phb *phb) +{ + return container_of(phb, struct npu, phb); +} + +static inline void npu_ioda_sel(struct npu *p, uint32_t table, + uint32_t addr, bool autoinc) +{ + out_be64(p->at_regs + NPU_IODA_ADDR, + (autoinc ? NPU_IODA_AD_AUTOINC : 0) | + SETFIELD(NPU_IODA_AD_TSEL, 0ul, table) | + SETFIELD(NPU_IODA_AD_TADR, 0ul, addr)); +} + +void npu_scom_init(struct npu_dev *dev); + +int64_t npu_dev_procedure(void *dev, struct pci_cfg_reg_filter *pcrf, + uint32_t offset, uint32_t len, uint32_t *data, + bool write); + +void npu_set_fence_state(struct npu *p, bool fence); +void npu_dev_procedure_reset(struct npu_dev *dev); + +#define NPUDBG(p, fmt, a...) prlog(PR_DEBUG, "NPU%d: " fmt, \ + (p)->phb.opal_id, ##a) +#define NPUINF(p, fmt, a...) prlog(PR_INFO, "NPU%d: " fmt, \ + (p)->phb.opal_id, ##a) + +#define NPUDEVDBG(p, fmt, a...) NPUDBG((p)->npu, fmt, ##a) +#define NPUDEVINF(p, fmt, a...) NPUINF((p)->npu, fmt, ##a) + +#endif /* __NPU_H */ |