blob: 95ac7f2c935022e16f7394496deb61d9458f9756 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef __CVMX_PCIE_H__
#define __CVMX_PCIE_H__
#define CVMX_PCIE_MAX_PORTS 4
#define CVMX_PCIE_PORTS \
((OCTEON_IS_MODEL(OCTEON_CN78XX) || OCTEON_IS_MODEL(OCTEON_CN73XX)) ? \
CVMX_PCIE_MAX_PORTS : \
(OCTEON_IS_MODEL(OCTEON_CN70XX) ? 3 : 2))
/*
* The physical memory base mapped by BAR1. 256MB at the end of the
* first 4GB.
*/
#define CVMX_PCIE_BAR1_PHYS_BASE ((1ull << 32) - (1ull << 28))
#define CVMX_PCIE_BAR1_PHYS_SIZE BIT_ULL(28)
/*
* The RC base of BAR1. gen1 has a 39-bit BAR2, gen2 has 41-bit BAR2,
* place BAR1 so it is the same for both.
*/
#define CVMX_PCIE_BAR1_RC_BASE BIT_ULL(41)
typedef union {
u64 u64;
struct {
u64 upper : 2; /* Normally 2 for XKPHYS */
u64 reserved_49_61 : 13; /* Must be zero */
u64 io : 1; /* 1 for IO space access */
u64 did : 5; /* PCIe DID = 3 */
u64 subdid : 3; /* PCIe SubDID = 1 */
u64 reserved_38_39 : 2; /* Must be zero */
u64 node : 2; /* Numa node number */
u64 es : 2; /* Endian swap = 1 */
u64 port : 2; /* PCIe port 0,1 */
u64 reserved_29_31 : 3; /* Must be zero */
u64 ty : 1;
u64 bus : 8;
u64 dev : 5;
u64 func : 3;
u64 reg : 12;
} config;
struct {
u64 upper : 2; /* Normally 2 for XKPHYS */
u64 reserved_49_61 : 13; /* Must be zero */
u64 io : 1; /* 1 for IO space access */
u64 did : 5; /* PCIe DID = 3 */
u64 subdid : 3; /* PCIe SubDID = 2 */
u64 reserved_38_39 : 2; /* Must be zero */
u64 node : 2; /* Numa node number */
u64 es : 2; /* Endian swap = 1 */
u64 port : 2; /* PCIe port 0,1 */
u64 address : 32; /* PCIe IO address */
} io;
struct {
u64 upper : 2; /* Normally 2 for XKPHYS */
u64 reserved_49_61 : 13; /* Must be zero */
u64 io : 1; /* 1 for IO space access */
u64 did : 5; /* PCIe DID = 3 */
u64 subdid : 3; /* PCIe SubDID = 3-6 */
u64 reserved_38_39 : 2; /* Must be zero */
u64 node : 2; /* Numa node number */
u64 address : 36; /* PCIe Mem address */
} mem;
} cvmx_pcie_address_t;
/**
* Return the Core virtual base address for PCIe IO access. IOs are
* read/written as an offset from this address.
*
* @param pcie_port PCIe port the IO is for
*
* Return: 64bit Octeon IO base address for read/write
*/
u64 cvmx_pcie_get_io_base_address(int pcie_port);
/**
* Size of the IO address region returned at address
* cvmx_pcie_get_io_base_address()
*
* @param pcie_port PCIe port the IO is for
*
* Return: Size of the IO window
*/
u64 cvmx_pcie_get_io_size(int pcie_port);
/**
* Return the Core virtual base address for PCIe MEM access. Memory is
* read/written as an offset from this address.
*
* @param pcie_port PCIe port the IO is for
*
* Return: 64bit Octeon IO base address for read/write
*/
u64 cvmx_pcie_get_mem_base_address(int pcie_port);
/**
* Size of the Mem address region returned at address
* cvmx_pcie_get_mem_base_address()
*
* @param pcie_port PCIe port the IO is for
*
* Return: Size of the Mem window
*/
u64 cvmx_pcie_get_mem_size(int pcie_port);
/**
* Initialize a PCIe port for use in host(RC) mode. It doesn't enumerate the bus.
*
* @param pcie_port PCIe port to initialize
*
* Return: Zero on success
*/
int cvmx_pcie_rc_initialize(int pcie_port);
/**
* Shutdown a PCIe port and put it in reset
*
* @param pcie_port PCIe port to shutdown
*
* Return: Zero on success
*/
int cvmx_pcie_rc_shutdown(int pcie_port);
/**
* Read 8bits from a Device's config space
*
* @param pcie_port PCIe port the device is on
* @param bus Sub bus
* @param dev Device ID
* @param fn Device sub function
* @param reg Register to access
*
* Return: Result of the read
*/
u8 cvmx_pcie_config_read8(int pcie_port, int bus, int dev, int fn, int reg);
/**
* Read 16bits from a Device's config space
*
* @param pcie_port PCIe port the device is on
* @param bus Sub bus
* @param dev Device ID
* @param fn Device sub function
* @param reg Register to access
*
* Return: Result of the read
*/
u16 cvmx_pcie_config_read16(int pcie_port, int bus, int dev, int fn, int reg);
/**
* Read 32bits from a Device's config space
*
* @param pcie_port PCIe port the device is on
* @param bus Sub bus
* @param dev Device ID
* @param fn Device sub function
* @param reg Register to access
*
* Return: Result of the read
*/
u32 cvmx_pcie_config_read32(int pcie_port, int bus, int dev, int fn, int reg);
/**
* Write 8bits to a Device's config space
*
* @param pcie_port PCIe port the device is on
* @param bus Sub bus
* @param dev Device ID
* @param fn Device sub function
* @param reg Register to access
* @param val Value to write
*/
void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, int reg, u8 val);
/**
* Write 16bits to a Device's config space
*
* @param pcie_port PCIe port the device is on
* @param bus Sub bus
* @param dev Device ID
* @param fn Device sub function
* @param reg Register to access
* @param val Value to write
*/
void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, int reg, u16 val);
/**
* Write 32bits to a Device's config space
*
* @param pcie_port PCIe port the device is on
* @param bus Sub bus
* @param dev Device ID
* @param fn Device sub function
* @param reg Register to access
* @param val Value to write
*/
void cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, int reg, u32 val);
/**
* Read a PCIe config space register indirectly. This is used for
* registers of the form PCIEEP_CFG??? and PCIERC?_CFG???.
*
* @param pcie_port PCIe port to read from
* @param cfg_offset Address to read
*
* Return: Value read
*/
u32 cvmx_pcie_cfgx_read(int pcie_port, u32 cfg_offset);
u32 cvmx_pcie_cfgx_read_node(int node, int pcie_port, u32 cfg_offset);
/**
* Write a PCIe config space register indirectly. This is used for
* registers of the form PCIEEP_CFG??? and PCIERC?_CFG???.
*
* @param pcie_port PCIe port to write to
* @param cfg_offset Address to write
* @param val Value to write
*/
void cvmx_pcie_cfgx_write(int pcie_port, u32 cfg_offset, u32 val);
void cvmx_pcie_cfgx_write_node(int node, int pcie_port, u32 cfg_offset, u32 val);
/**
* Write a 32bit value to the Octeon NPEI register space
*
* @param address Address to write to
* @param val Value to write
*/
static inline void cvmx_pcie_npei_write32(u64 address, u32 val)
{
cvmx_write64_uint32(address ^ 4, val);
cvmx_read64_uint32(address ^ 4);
}
/**
* Read a 32bit value from the Octeon NPEI register space
*
* @param address Address to read
* Return: The result
*/
static inline u32 cvmx_pcie_npei_read32(u64 address)
{
return cvmx_read64_uint32(address ^ 4);
}
/**
* Initialize a PCIe port for use in target(EP) mode.
*
* @param pcie_port PCIe port to initialize
*
* Return: Zero on success
*/
int cvmx_pcie_ep_initialize(int pcie_port);
/**
* Wait for posted PCIe read/writes to reach the other side of
* the internal PCIe switch. This will insure that core
* read/writes are posted before anything after this function
* is called. This may be necessary when writing to memory that
* will later be read using the DMA/PKT engines.
*
* @param pcie_port PCIe port to wait for
*/
void cvmx_pcie_wait_for_pending(int pcie_port);
/**
* Returns if a PCIe port is in host or target mode.
*
* @param pcie_port PCIe port number (PEM number)
*
* Return: 0 if PCIe port is in target mode, !0 if in host mode.
*/
int cvmx_pcie_is_host_mode(int pcie_port);
#endif