244 lines
7.8 KiB
C
244 lines
7.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Huawei Hifc PCI Express Linux driver
|
|
* Copyright(c) 2017 Huawei Technologies Co., Ltd
|
|
*
|
|
*/
|
|
|
|
#ifndef HIFC_HWIF_H
|
|
#define HIFC_HWIF_H
|
|
|
|
#include "hifc_hwdev.h"
|
|
|
|
#define HIFC_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT 60000
|
|
#define HIFC_CSR_GLOBAL_BASE_ADDR 0x4000
|
|
/* HW interface registers */
|
|
#define HIFC_CSR_FUNC_ATTR0_ADDR 0x0
|
|
#define HIFC_CSR_FUNC_ATTR1_ADDR 0x4
|
|
#define HIFC_CSR_FUNC_ATTR2_ADDR 0x8
|
|
#define HIFC_CSR_FUNC_ATTR4_ADDR 0x10
|
|
|
|
#define HIFC_CSR_FUNC_ATTR5_ADDR 0x14
|
|
#define HIFC_PCI_MSIX_ENTRY_SIZE 16
|
|
#define HIFC_PCI_MSIX_ENTRY_VECTOR_CTRL 12
|
|
#define HIFC_PCI_MSIX_ENTRY_CTRL_MASKBIT 1
|
|
|
|
/* total doorbell or direct wqe size is 512kB, db num: 128, dwqe: 128*/
|
|
#define HIFC_DB_DWQE_SIZE 0x00080000
|
|
/* db/dwqe page size: 4K */
|
|
#define HIFC_DB_PAGE_SIZE 0x00001000ULL
|
|
#define HIFC_DB_MAX_AREAS (HIFC_DB_DWQE_SIZE / HIFC_DB_PAGE_SIZE)
|
|
|
|
#define HIFC_ELECTION_BASE 0x200
|
|
#define HIFC_PPF_ELECTION_STRIDE 0x4
|
|
#define HIFC_CSR_MAX_PORTS 4
|
|
#define HIFC_CSR_PPF_ELECTION_ADDR \
|
|
(HIFC_CSR_GLOBAL_BASE_ADDR + HIFC_ELECTION_BASE)
|
|
|
|
#define HIFC_CSR_GLOBAL_MPF_ELECTION_ADDR \
|
|
(HIFC_CSR_GLOBAL_BASE_ADDR + HIFC_ELECTION_BASE + \
|
|
HIFC_CSR_MAX_PORTS * HIFC_PPF_ELECTION_STRIDE)
|
|
#define DB_IDX(db, db_base) \
|
|
((u32)(((ulong)(db) - (ulong)(db_base)) / \
|
|
HIFC_DB_PAGE_SIZE))
|
|
|
|
#define HIFC_AF0_FUNC_GLOBAL_IDX_SHIFT 0
|
|
#define HIFC_AF0_P2P_IDX_SHIFT 10
|
|
#define HIFC_AF0_PCI_INTF_IDX_SHIFT 14
|
|
#define HIFC_AF0_VF_IN_PF_SHIFT 16
|
|
#define HIFC_AF0_FUNC_TYPE_SHIFT 24
|
|
#define HIFC_AF0_FUNC_GLOBAL_IDX_MASK 0x3FF
|
|
#define HIFC_AF0_P2P_IDX_MASK 0xF
|
|
#define HIFC_AF0_PCI_INTF_IDX_MASK 0x3
|
|
#define HIFC_AF0_VF_IN_PF_MASK 0xFF
|
|
#define HIFC_AF0_FUNC_TYPE_MASK 0x1
|
|
|
|
#define HIFC_AF0_GET(val, member) \
|
|
(((val) >> HIFC_AF0_##member##_SHIFT) & HIFC_AF0_##member##_MASK)
|
|
|
|
#define HIFC_AF1_PPF_IDX_SHIFT 0
|
|
#define HIFC_AF1_AEQS_PER_FUNC_SHIFT 8
|
|
#define HIFC_AF1_CEQS_PER_FUNC_SHIFT 12
|
|
#define HIFC_AF1_IRQS_PER_FUNC_SHIFT 20
|
|
#define HIFC_AF1_DMA_ATTR_PER_FUNC_SHIFT 24
|
|
#define HIFC_AF1_MGMT_INIT_STATUS_SHIFT 30
|
|
#define HIFC_AF1_PF_INIT_STATUS_SHIFT 31
|
|
|
|
#define HIFC_AF1_PPF_IDX_MASK 0x1F
|
|
#define HIFC_AF1_AEQS_PER_FUNC_MASK 0x3
|
|
#define HIFC_AF1_CEQS_PER_FUNC_MASK 0x7
|
|
#define HIFC_AF1_IRQS_PER_FUNC_MASK 0xF
|
|
#define HIFC_AF1_DMA_ATTR_PER_FUNC_MASK 0x7
|
|
#define HIFC_AF1_MGMT_INIT_STATUS_MASK 0x1
|
|
#define HIFC_AF1_PF_INIT_STATUS_MASK 0x1
|
|
|
|
#define HIFC_AF1_GET(val, member) \
|
|
(((val) >> HIFC_AF1_##member##_SHIFT) & HIFC_AF1_##member##_MASK)
|
|
|
|
#define HIFC_AF4_OUTBOUND_CTRL_SHIFT 0
|
|
#define HIFC_AF4_DOORBELL_CTRL_SHIFT 1
|
|
#define HIFC_AF4_OUTBOUND_CTRL_MASK 0x1
|
|
#define HIFC_AF4_DOORBELL_CTRL_MASK 0x1
|
|
|
|
#define HIFC_AF4_GET(val, member) \
|
|
(((val) >> HIFC_AF4_##member##_SHIFT) & HIFC_AF4_##member##_MASK)
|
|
|
|
#define HIFC_AF4_SET(val, member) \
|
|
(((val) & HIFC_AF4_##member##_MASK) << HIFC_AF4_##member##_SHIFT)
|
|
|
|
#define HIFC_AF4_CLEAR(val, member) \
|
|
((val) & (~(HIFC_AF4_##member##_MASK << \
|
|
HIFC_AF4_##member##_SHIFT)))
|
|
|
|
#define HIFC_AF5_PF_STATUS_SHIFT 0
|
|
#define HIFC_AF5_PF_STATUS_MASK 0xFFFF
|
|
|
|
#define HIFC_AF5_SET(val, member) \
|
|
(((val) & HIFC_AF5_##member##_MASK) << HIFC_AF5_##member##_SHIFT)
|
|
|
|
#define HIFC_AF5_GET(val, member) \
|
|
(((val) >> HIFC_AF5_##member##_SHIFT) & HIFC_AF5_##member##_MASK)
|
|
|
|
#define HIFC_PPF_ELECTION_IDX_SHIFT 0
|
|
#define HIFC_PPF_ELECTION_IDX_MASK 0x1F
|
|
|
|
#define HIFC_PPF_ELECTION_SET(val, member) \
|
|
(((val) & HIFC_PPF_ELECTION_##member##_MASK) << \
|
|
HIFC_PPF_ELECTION_##member##_SHIFT)
|
|
|
|
#define HIFC_PPF_ELECTION_GET(val, member) \
|
|
(((val) >> HIFC_PPF_ELECTION_##member##_SHIFT) & \
|
|
HIFC_PPF_ELECTION_##member##_MASK)
|
|
|
|
#define HIFC_PPF_ELECTION_CLEAR(val, member) \
|
|
((val) & (~(HIFC_PPF_ELECTION_##member##_MASK \
|
|
<< HIFC_PPF_ELECTION_##member##_SHIFT)))
|
|
|
|
#define HIFC_MPF_ELECTION_IDX_SHIFT 0
|
|
#define HIFC_MPF_ELECTION_IDX_MASK 0x1F
|
|
|
|
#define HIFC_MPF_ELECTION_SET(val, member) \
|
|
(((val) & HIFC_MPF_ELECTION_##member##_MASK) << \
|
|
HIFC_MPF_ELECTION_##member##_SHIFT)
|
|
|
|
#define HIFC_MPF_ELECTION_GET(val, member) \
|
|
(((val) >> HIFC_MPF_ELECTION_##member##_SHIFT) & \
|
|
HIFC_MPF_ELECTION_##member##_MASK)
|
|
|
|
#define HIFC_MPF_ELECTION_CLEAR(val, member) \
|
|
((val) & (~(HIFC_MPF_ELECTION_##member##_MASK \
|
|
<< HIFC_MPF_ELECTION_##member##_SHIFT)))
|
|
|
|
#define HIFC_HWIF_NUM_AEQS(hwif) ((hwif)->attr.num_aeqs)
|
|
#define HIFC_HWIF_NUM_CEQS(hwif) ((hwif)->attr.num_ceqs)
|
|
#define HIFC_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx)
|
|
#define HIFC_PCI_INTF_IDX(hwif) ((hwif)->attr.pci_intf_idx)
|
|
|
|
#define HIFC_FUNC_TYPE(dev) ((dev)->hwif->attr.func_type)
|
|
#define HIFC_IS_PPF(dev) (HIFC_FUNC_TYPE(dev) == TYPE_PPF)
|
|
|
|
enum hifc_pcie_nosnoop {
|
|
HIFC_PCIE_SNOOP = 0,
|
|
HIFC_PCIE_NO_SNOOP = 1,
|
|
};
|
|
|
|
enum hifc_pcie_tph {
|
|
HIFC_PCIE_TPH_DISABLE = 0,
|
|
HIFC_PCIE_TPH_ENABLE = 1,
|
|
};
|
|
|
|
enum hifc_pf_status {
|
|
HIFC_PF_STATUS_INIT = 0X0,
|
|
HIFC_PF_STATUS_ACTIVE_FLAG = 0x11,
|
|
HIFC_PF_STATUS_FLR_START_FLAG = 0x12,
|
|
HIFC_PF_STATUS_FLR_FINISH_FLAG = 0x13,
|
|
};
|
|
|
|
enum hifc_outbound_ctrl {
|
|
ENABLE_OUTBOUND = 0x0,
|
|
DISABLE_OUTBOUND = 0x1,
|
|
};
|
|
|
|
enum hifc_doorbell_ctrl {
|
|
ENABLE_DOORBELL = 0x0,
|
|
DISABLE_DOORBELL = 0x1,
|
|
};
|
|
|
|
struct hifc_free_db_area {
|
|
u32 db_idx[HIFC_DB_MAX_AREAS];
|
|
u32 num_free;
|
|
u32 alloc_pos;
|
|
u32 return_pos;
|
|
/* spinlock for allocating doorbell area */
|
|
spinlock_t idx_lock;
|
|
};
|
|
|
|
enum func_type {
|
|
TYPE_PF,
|
|
TYPE_VF,
|
|
TYPE_PPF,
|
|
TYPE_UNKNOWN,
|
|
};
|
|
|
|
struct hifc_func_attr {
|
|
u16 func_global_idx;
|
|
u8 port_to_port_idx;
|
|
u8 pci_intf_idx;
|
|
u8 vf_in_pf;
|
|
enum func_type func_type;
|
|
|
|
u8 mpf_idx;
|
|
|
|
u8 ppf_idx;
|
|
|
|
u16 num_irqs; /* max: 2 ^ 15 */
|
|
u8 num_aeqs; /* max: 2 ^ 3 */
|
|
u8 num_ceqs; /* max: 2 ^ 7 */
|
|
|
|
u8 num_dma_attr; /* max: 2 ^ 6 */
|
|
};
|
|
|
|
struct hifc_hwif {
|
|
u8 __iomem *cfg_regs_base;
|
|
u8 __iomem *intr_regs_base;
|
|
u64 db_base_phy;
|
|
u8 __iomem *db_base;
|
|
|
|
#if defined(__aarch64__)
|
|
void __iomem *dwqe_mapping;
|
|
#else
|
|
struct io_mapping *dwqe_mapping;
|
|
#endif
|
|
struct hifc_free_db_area free_db_area;
|
|
struct hifc_func_attr attr;
|
|
void *pdev;
|
|
};
|
|
|
|
struct hifc_dma_addr_align {
|
|
u32 real_size;
|
|
void *ori_vaddr;
|
|
dma_addr_t ori_paddr;
|
|
void *align_vaddr;
|
|
dma_addr_t align_paddr;
|
|
};
|
|
|
|
u32 hifc_hwif_read_reg(struct hifc_hwif *hwif, u32 reg);
|
|
void hifc_hwif_write_reg(struct hifc_hwif *hwif, u32 reg, u32 val);
|
|
void hifc_set_pf_status(struct hifc_hwif *hwif, enum hifc_pf_status status);
|
|
enum hifc_pf_status hifc_get_pf_status(struct hifc_hwif *hwif);
|
|
enum hifc_doorbell_ctrl
|
|
hifc_get_doorbell_ctrl_status(struct hifc_hwif *hwif);
|
|
enum hifc_outbound_ctrl
|
|
hifc_get_outbound_ctrl_status(struct hifc_hwif *hwif);
|
|
void hifc_enable_doorbell(struct hifc_hwif *hwif);
|
|
void hifc_disable_doorbell(struct hifc_hwif *hwif);
|
|
int hifc_init_hwif(struct hifc_hwdev *hwdev, void *cfg_reg_base,
|
|
void *intr_reg_base, u64 db_base_phy,
|
|
void *db_base, void *dwqe_mapping);
|
|
void hifc_free_hwif(struct hifc_hwdev *hwdev);
|
|
int hifc_dma_alloc_coherent_align(void *dev_hdl, u64 size, u64 align,
|
|
unsigned flag,
|
|
struct hifc_dma_addr_align *mem_align);
|
|
void hifc_dma_free_coherent_align(void *dev_hdl,
|
|
struct hifc_dma_addr_align *mem_align);
|
|
#endif
|