soc/qualcomm: Add PCIe support
Add PCIe platform driver for Qualcomm platforms. Reference: - linux/drivers/pci/controller/dwc/pcie-qcom.c - Linux driver base commit: 82a823833f4e3769e82cdb4df1bc2234bc65b16c BUG=b:182963902,b:216686574,b:181098581 TEST=Verified on Qualcomm sc7280 development board with NVMe card (Koixa NVMe, Model-KBG40ZPZ256G with FW AEGA0102). Confirmed NVMe is getting detected in response to 'storage init' command in depthcharge CLI prompt. Output logs: ->dpch: storage init Initializing NVMe controller 1e0f:0001 Identified NVMe model KBG40ZPZ256G TOSHIBA MEMORY Added NVMe drive "NVMe Namespace 1" lbasize:512, count:0x1dcf32b0 * 0: NVMe Namespace 1 1 devices total Also verified NVMe boot path, that is depthcharge is able to load the kernel image from NVMe storage. Change-Id: Iccf60aa56541f5230fa9c3f821d7709615c36631 Signed-off-by: Prasad Malisetty <quic_pmaliset@quicinc.com> Signed-off-by: Veerabhadrarao Badiganti <quic_vbadigan@quicinc.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/53902 Reviewed-by: Shelley Chen <shchen@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
37bf8c6dd5
commit
b66675d433
225
src/soc/qualcomm/common/include/soc/pcie.h
Normal file
225
src/soc/qualcomm/common/include/soc/pcie.h
Normal file
@ -0,0 +1,225 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _PCIE_H_
|
||||
#define _PCIE_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <device/device.h>
|
||||
#include <soc/gpio.h>
|
||||
|
||||
/*
|
||||
* Config, IO and MMIO space offsets relative to controller base and sizes.
|
||||
*
|
||||
* EP config space starts at 1MB offset from controller base.
|
||||
* EP config space size would be 4KB for each endpoint.
|
||||
* IO space starts at 2MB offset from controller base and its of 1MB size.
|
||||
* MMIO space starts from 3MB offset from controller base and it can be up to
|
||||
* end of space reserved for PCIe.
|
||||
*/
|
||||
#define PCIE_EP_CONF_OFFSET 0x100000
|
||||
#define PCIE_EP_CONF_SIZE 0x1000
|
||||
#define PCIE_IO_SPACE_OFFSET 0x200000
|
||||
#define PCIE_IO_SPACE_SIZE 0x100000
|
||||
#define PCIE_MMIO_SPACE_OFFSET 0x300000
|
||||
|
||||
/* Parf Registers */
|
||||
#define PCIE_PARF_SYS_CTRL 0x00
|
||||
#define MAC_PHY_PWRDOWN_MUX_EN BIT(29)
|
||||
#define PCIE_PARF_PHY_CTRL 0x40
|
||||
#define PHY_PWR_DOWN BIT(0)
|
||||
#define PCIE_PARF_MHI_CLOCK_RESET_CTRL 0x174
|
||||
#define MHI_BYPASS BIT(4)
|
||||
#define PCIE_PARF_LTSSM 0x1B0
|
||||
#define LTSSM_EN BIT(8)
|
||||
#define PCIE_PARF_DBI_BASE_ADDR 0x350
|
||||
#define PCIE_PARF_DEVICE_TYPE 0x1000
|
||||
#define DEVICE_TYPE_RC 0x4
|
||||
#define PCIE_PARF_BDF_TO_SID_CFG 0x2C00
|
||||
#define BDF_TO_SID_BYPASS BIT(0)
|
||||
|
||||
/* ELBI */
|
||||
#define PCIE3X2_ELBI_SYS_STTS 0x08
|
||||
#define XMLH_LINK_UP 0x400
|
||||
|
||||
/* DBI Registers */
|
||||
#define PCIE_LINK_CAPABILITY 0x7c
|
||||
#define PCIE_LINK_CTL_2 0xa0
|
||||
#define TARGET_LINK_SPEED_MASK 0xf
|
||||
#define LINK_SPEED_GEN_1 0x1
|
||||
#define LINK_SPEED_GEN_2 0x2
|
||||
#define LINK_SPEED_GEN_3 0x3
|
||||
#define PCIE_LINK_UP_MS 100
|
||||
#define LINK_WAIT_MAX_RETRIES 10
|
||||
|
||||
#define COMMAND_MASK 0xffff
|
||||
|
||||
#define TYPE1_HDR_BUS_NUM_MASK 0xffffff
|
||||
#define RC_PRI_BUS_NUM 0x0
|
||||
#define RC_SEC_BUS_NUM 0x1
|
||||
#define RC_SUB_BUS_NUM 0xff
|
||||
#define ROOT_PORT_BUS_NUM ((RC_SUB_BUS_NUM << 16) | \
|
||||
(RC_SEC_BUS_NUM << 8) | \
|
||||
RC_PRI_BUS_NUM)
|
||||
|
||||
/* Synopsys-specific PCIe configuration registers */
|
||||
#define PCIE_DBI_MISC_CONTROL_1_OFF 0x8BC
|
||||
#define PCIE_DBI_RO_WR_EN BIT(0)
|
||||
|
||||
#define PCIE_3x2_NUM_LANES 2
|
||||
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
|
||||
#define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8)
|
||||
#define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8)
|
||||
#define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8)
|
||||
#define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8)
|
||||
#define PORT_LOGIC_LINK_WIDTH_8_LANES (0x8 << 8)
|
||||
|
||||
#define PCIE_PORT_LINK_CONTROL 0x710
|
||||
#define PORT_LINK_MODE_MASK (0x3f << 16)
|
||||
#define PORT_LINK_MODE_1_LANES (0x1 << 16)
|
||||
#define PORT_LINK_MODE_2_LANES (0x3 << 16)
|
||||
#define PORT_LINK_MODE_4_LANES (0x7 << 16)
|
||||
#define PORT_LINK_MODE_8_LANES (0xf << 16)
|
||||
|
||||
/*
|
||||
* iATU Unroll-specific register definitions
|
||||
* From DesignWare PCIe core v4.80, the address translation
|
||||
* will be made by unroll
|
||||
*/
|
||||
#define PCIE_ATU_REGION_INDEX1 0x1
|
||||
#define PCIE_ATU_REGION_INDEX0 0x0
|
||||
#define PCIE_ATU_TYPE_MEM 0x0
|
||||
#define PCIE_ATU_TYPE_CFG0 0x4
|
||||
#define PCIE_ATU_TYPE_CFG1 0x5
|
||||
#define PCIE_ATU_ENABLE BIT(31)
|
||||
#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
|
||||
#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
|
||||
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
|
||||
|
||||
#define PCIE_ATU_UNR_REGION_CTRL1 0x00
|
||||
#define PCIE_ATU_UNR_REGION_CTRL2 0x04
|
||||
#define PCIE_ATU_UNR_LOWER_BASE 0x08
|
||||
#define PCIE_ATU_UNR_UPPER_BASE 0x0C
|
||||
#define PCIE_ATU_UNR_LIMIT 0x10
|
||||
#define PCIE_ATU_UNR_LOWER_TARGET 0x14
|
||||
#define PCIE_ATU_UNR_UPPER_TARGET 0x18
|
||||
|
||||
#define LINK_WAIT_MAX_IATU_RETRIES 5
|
||||
#define LINK_WAIT_IATU 1000
|
||||
|
||||
/* PHY Specific fields */
|
||||
#define QPHY_SW_RESET 0x00
|
||||
#define SW_RESET BIT(0)
|
||||
#define QPHY_PCS_STATUS 0x14
|
||||
#define PHY_STATUS BIT(6)
|
||||
#define QPHY_PCS_PWR_DWN_CNTRL 0x40
|
||||
#define SW_PWRDN BIT(0)
|
||||
#define REFCLK_DRV_DSBL BIT(1)
|
||||
#define QPHY_START_CTRL 0x44
|
||||
#define SERDES_START BIT(0)
|
||||
#define PCS_START BIT(1)
|
||||
|
||||
/* Register address builder */
|
||||
#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((region) << 9)
|
||||
#define lower_32_bits(n) ((u32)(n))
|
||||
#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
|
||||
|
||||
#define QMP_PHY_INIT_CFG(o, v) \
|
||||
{ \
|
||||
.offset = o, \
|
||||
.val = v, \
|
||||
.lane_mask = 0xff, \
|
||||
}
|
||||
|
||||
typedef uint64_t pci_addr_t;
|
||||
typedef uint64_t pci_size_t;
|
||||
|
||||
struct qcom_qmp_phy_init_tbl {
|
||||
unsigned int offset;
|
||||
uint32_t val;
|
||||
unsigned short lane_mask;
|
||||
};
|
||||
|
||||
struct pcie_region {
|
||||
pci_addr_t bus_start; /* BDF */
|
||||
uint64_t phys_start; /* Start in physical address space */
|
||||
pci_size_t size; /* Size */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pcie_cntlr_cfg_t - QCOM DW PCIe Controller state
|
||||
*
|
||||
* @lanes : Number of lanes
|
||||
* @cfg_size : The size of the configuration space
|
||||
* @cfg_base : The base address of config space
|
||||
* @dbi_base : The base address of dbi register space
|
||||
* @atu_base : The base address of address translation unit
|
||||
* @parf : The base address of PARF register space
|
||||
* @elbi : The base address of ELBI space
|
||||
* @phy : Base address of the PHY controller
|
||||
* @pcie_bcr : address of the block controller register
|
||||
* @reset : PERST gpio
|
||||
* @io : Base address of the IO region
|
||||
* @mem : Base address of memory region
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int lanes;
|
||||
unsigned int cfg_size;
|
||||
void *cfg_base;
|
||||
void *dbi_base;
|
||||
void *atu_base;
|
||||
void *parf;
|
||||
void *elbi;
|
||||
void *pcie_bcr;
|
||||
void *qmp_phy_bcr;
|
||||
gpio_t perst;
|
||||
/* IO and MEM PCI regions */
|
||||
struct pcie_region io;
|
||||
struct pcie_region mem;
|
||||
} pcie_cntlr_cfg_t;
|
||||
|
||||
typedef struct {
|
||||
void *qmp_phy_base;
|
||||
void *serdes;
|
||||
void *tx0;
|
||||
void *rx0;
|
||||
void *pcs;
|
||||
void *tx1;
|
||||
void *rx1;
|
||||
void *pcs_misc;
|
||||
|
||||
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
|
||||
const struct qcom_qmp_phy_init_tbl *serdes_tbl;
|
||||
unsigned int serdes_tbl_num;
|
||||
const struct qcom_qmp_phy_init_tbl *serdes_tbl_sec;
|
||||
unsigned int serdes_tbl_num_sec;
|
||||
const struct qcom_qmp_phy_init_tbl *tx_tbl;
|
||||
unsigned int tx_tbl_num;
|
||||
const struct qcom_qmp_phy_init_tbl *tx_tbl_sec;
|
||||
unsigned int tx_tbl_num_sec;
|
||||
const struct qcom_qmp_phy_init_tbl *rx_tbl;
|
||||
unsigned int rx_tbl_num;
|
||||
const struct qcom_qmp_phy_init_tbl *rx_tbl_sec;
|
||||
unsigned int rx_tbl_num_sec;
|
||||
const struct qcom_qmp_phy_init_tbl *pcs_tbl;
|
||||
unsigned int pcs_tbl_num;
|
||||
const struct qcom_qmp_phy_init_tbl *pcs_tbl_sec;
|
||||
unsigned int pcs_tbl_num_sec;
|
||||
const struct qcom_qmp_phy_init_tbl *pcs_misc_tbl;
|
||||
unsigned int pcs_misc_tbl_num;
|
||||
const struct qcom_qmp_phy_init_tbl *pcs_misc_tbl_sec;
|
||||
unsigned int pcs_misc_tbl_num_sec;
|
||||
} pcie_qmp_phy_cfg_t;
|
||||
|
||||
struct qcom_pcie_cntlr_t {
|
||||
pcie_cntlr_cfg_t *cntlr_cfg;
|
||||
pcie_qmp_phy_cfg_t *qmp_phy_cfg;
|
||||
};
|
||||
|
||||
int qcom_dw_pcie_enable_clock(void);
|
||||
int qcom_dw_pcie_enable_pipe_clock(void);
|
||||
void gcom_pcie_power_on_ep(void);
|
||||
void gcom_pcie_get_config(struct qcom_pcie_cntlr_t *host_cfg);
|
||||
void qcom_pci_domain_read_resources(struct device *dev);
|
||||
void qcom_setup_pcie_host(struct device *dev);
|
||||
|
||||
#endif
|
272
src/soc/qualcomm/common/include/soc/qcom_qmp_phy.h
Normal file
272
src/soc/qualcomm/common/include/soc/qcom_qmp_phy.h
Normal file
@ -0,0 +1,272 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef QCOM_PHY_QMP_H_
|
||||
#define QCOM_PHY_QMP_H_
|
||||
|
||||
/* Only for QMP V4 PHY - QSERDES COM registers */
|
||||
#define QSERDES_V4_COM_SSC_EN_CENTER 0x010
|
||||
#define QSERDES_V4_COM_SSC_PER1 0x01c
|
||||
#define QSERDES_V4_COM_SSC_PER2 0x020
|
||||
#define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0 0x024
|
||||
#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0 0x028
|
||||
#define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1 0x030
|
||||
#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1 0x034
|
||||
#define QSERDES_V4_COM_CLK_ENABLE1 0x048
|
||||
#define QSERDES_V4_COM_SYSCLK_BUF_ENABLE 0x050
|
||||
#define QSERDES_V4_COM_PLL_IVCO 0x058
|
||||
#define QSERDES_V4_COM_CMN_IPTRIM 0x060
|
||||
#define QSERDES_V4_COM_CP_CTRL_MODE0 0x074
|
||||
#define QSERDES_V4_COM_CP_CTRL_MODE1 0x078
|
||||
#define QSERDES_V4_COM_PLL_RCTRL_MODE0 0x07c
|
||||
#define QSERDES_V4_COM_PLL_RCTRL_MODE1 0x080
|
||||
#define QSERDES_V4_COM_PLL_CCTRL_MODE0 0x084
|
||||
#define QSERDES_V4_COM_PLL_CCTRL_MODE1 0x088
|
||||
#define QSERDES_V4_COM_SYSCLK_EN_SEL 0x094
|
||||
#define QSERDES_V4_COM_LOCK_CMP_EN 0x0a4
|
||||
#define QSERDES_V4_COM_LOCK_CMP1_MODE0 0x0ac
|
||||
#define QSERDES_V4_COM_LOCK_CMP2_MODE0 0x0b0
|
||||
#define QSERDES_V4_COM_LOCK_CMP1_MODE1 0x0b4
|
||||
#define QSERDES_V4_COM_DEC_START_MODE0 0x0bc
|
||||
#define QSERDES_V4_COM_LOCK_CMP2_MODE1 0x0b8
|
||||
#define QSERDES_V4_COM_DEC_START_MODE1 0x0c4
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START1_MODE0 0x0cc
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START2_MODE0 0x0d0
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START3_MODE0 0x0d4
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START1_MODE1 0x0d8
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START2_MODE1 0x0dc
|
||||
#define QSERDES_V4_COM_DIV_FRAC_START3_MODE1 0x0e0
|
||||
#define QSERDES_V4_COM_VCO_TUNE_MAP 0x10c
|
||||
#define QSERDES_V4_COM_VCO_TUNE1_MODE0 0x110
|
||||
#define QSERDES_V4_COM_VCO_TUNE2_MODE0 0x114
|
||||
#define QSERDES_V4_COM_VCO_TUNE1_MODE1 0x118
|
||||
#define QSERDES_V4_COM_VCO_TUNE2_MODE1 0x11c
|
||||
#define QSERDES_V4_COM_VCO_TUNE_INITVAL2 0x124
|
||||
#define QSERDES_V4_COM_CLK_SELECT 0x154
|
||||
#define QSERDES_V4_COM_HSCLK_SEL 0x158
|
||||
#define QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL 0x15c
|
||||
#define QSERDES_V4_COM_CORECLK_DIV_MODE1 0x16c
|
||||
#define QSERDES_V4_COM_SVS_MODE_CLK_SEL 0x184
|
||||
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x1ac
|
||||
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1b0
|
||||
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0x1b4
|
||||
#define QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL 0x1bc
|
||||
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1b8
|
||||
|
||||
/* Only for QMP V4 PHY - TX registers */
|
||||
#define QSERDES_V4_TX_RES_CODE_LANE_TX 0x34
|
||||
#define QSERDES_V4_TX_RES_CODE_LANE_RX 0x38
|
||||
#define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX 0x3c
|
||||
#define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX 0x40
|
||||
#define QSERDES_V4_TX_LANE_MODE_1 0x84
|
||||
#define QSERDES_V4_TX_LANE_MODE_2 0x88
|
||||
#define QSERDES_V4_TX_RCV_DETECT_LVL_2 0x9c
|
||||
#define QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1 0xd8
|
||||
#define QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1 0xdC
|
||||
#define QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1 0xe0
|
||||
#define QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1 0xe4
|
||||
#define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xb8
|
||||
#define QSERDES_V4_TX_PI_QEC_CTRL 0x104
|
||||
|
||||
/* Only for QMP V4 PHY - RX registers */
|
||||
#define QSERDES_V4_RX_UCDR_FO_GAIN 0x008
|
||||
#define QSERDES_V4_RX_UCDR_SO_GAIN 0x014
|
||||
#define QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN 0x030
|
||||
#define QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034
|
||||
#define QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW 0x03c
|
||||
#define QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH 0x040
|
||||
#define QSERDES_V4_RX_UCDR_PI_CONTROLS 0x044
|
||||
#define QSERDES_V4_RX_UCDR_PI_CTRL2 0x048
|
||||
#define QSERDES_V4_RX_UCDR_SB2_THRESH1 0x04c
|
||||
#define QSERDES_V4_RX_UCDR_SB2_THRESH2 0x050
|
||||
#define QSERDES_V4_RX_UCDR_SB2_GAIN1 0x054
|
||||
#define QSERDES_V4_RX_UCDR_SB2_GAIN2 0x058
|
||||
#define QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE 0x060
|
||||
#define QSERDES_V4_RX_RCLK_AUXDATA_SEL 0x064
|
||||
#define QSERDES_V4_RX_AC_JTAG_ENABLE 0x068
|
||||
#define QSERDES_V4_RX_AC_JTAG_MODE 0x078
|
||||
#define QSERDES_V4_RX_RX_TERM_BW 0x080
|
||||
#define QSERDES_V4_RX_VGA_CAL_CNTRL1 0x0d4
|
||||
#define QSERDES_V4_RX_VGA_CAL_CNTRL2 0x0d8
|
||||
#define QSERDES_V4_RX_GM_CAL 0x0dc
|
||||
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1 0x0e8
|
||||
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2 0x0ec
|
||||
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3 0x0f0
|
||||
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4 0x0f4
|
||||
#define QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW 0x0f8
|
||||
#define QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH 0x0fc
|
||||
#define QSERDES_V4_RX_RX_IDAC_MEASURE_TIME 0x100
|
||||
#define QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110
|
||||
#define QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x114
|
||||
#define QSERDES_V4_RX_SIGDET_ENABLES 0x118
|
||||
#define QSERDES_V4_RX_SIGDET_CNTRL 0x11c
|
||||
#define QSERDES_V4_RX_SIGDET_LVL 0x120
|
||||
#define QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL 0x124
|
||||
#define QSERDES_V4_RX_RX_BAND 0x128
|
||||
#define QSERDES_V4_RX_RX_MODE_00_LOW 0x170
|
||||
#define QSERDES_V4_RX_RX_MODE_00_HIGH 0x174
|
||||
#define QSERDES_V4_RX_RX_MODE_00_HIGH2 0x178
|
||||
#define QSERDES_V4_RX_RX_MODE_00_HIGH3 0x17c
|
||||
#define QSERDES_V4_RX_RX_MODE_00_HIGH4 0x180
|
||||
#define QSERDES_V4_RX_RX_MODE_01_LOW 0x184
|
||||
#define QSERDES_V4_RX_RX_MODE_01_HIGH 0x188
|
||||
#define QSERDES_V4_RX_RX_MODE_01_HIGH2 0x18c
|
||||
#define QSERDES_V4_RX_RX_MODE_01_HIGH3 0x190
|
||||
#define QSERDES_V4_RX_RX_MODE_01_HIGH4 0x194
|
||||
#define QSERDES_V4_RX_RX_MODE_10_LOW 0x198
|
||||
#define QSERDES_V4_RX_RX_MODE_10_HIGH 0x19c
|
||||
#define QSERDES_V4_RX_RX_MODE_10_HIGH2 0x1a0
|
||||
#define QSERDES_V4_RX_RX_MODE_10_HIGH3 0x1a4
|
||||
#define QSERDES_V4_RX_RX_MODE_10_HIGH4 0x1a8
|
||||
#define QSERDES_V4_RX_DFE_EN_TIMER 0x1b4
|
||||
#define QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET 0x1b8
|
||||
#define QSERDES_V4_RX_DCC_CTRL1 0x1bc
|
||||
#define QSERDES_V4_RX_VTH_CODE 0x1c4
|
||||
|
||||
/* Only for QMP V4 PHY - PCIe PCS registers */
|
||||
#define QPHY_V4_PCS_SW_RESET 0x000
|
||||
#define QPHY_V4_PCS_REVISION_ID0 0x004
|
||||
#define QPHY_V4_PCS_REVISION_ID1 0x008
|
||||
#define QPHY_V4_PCS_REVISION_ID2 0x00c
|
||||
#define QPHY_V4_PCS_REVISION_ID3 0x010
|
||||
#define QPHY_V4_PCS_PCS_STATUS1 0x014
|
||||
#define QPHY_V4_PCS_PCS_STATUS2 0x018
|
||||
#define QPHY_V4_PCS_PCS_STATUS3 0x01c
|
||||
#define QPHY_V4_PCS_PCS_STATUS4 0x020
|
||||
#define QPHY_V4_PCS_PCS_STATUS5 0x024
|
||||
#define QPHY_V4_PCS_PCS_STATUS6 0x028
|
||||
#define QPHY_V4_PCS_PCS_STATUS7 0x02c
|
||||
#define QPHY_V4_PCS_DEBUG_BUS_0_STATUS 0x030
|
||||
#define QPHY_V4_PCS_DEBUG_BUS_1_STATUS 0x034
|
||||
#define QPHY_V4_PCS_DEBUG_BUS_2_STATUS 0x038
|
||||
#define QPHY_V4_PCS_DEBUG_BUS_3_STATUS 0x03c
|
||||
#define QPHY_V4_PCS_POWER_DOWN_CONTROL 0x040
|
||||
#define QPHY_V4_PCS_START_CONTROL 0x044
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL1 0x048
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL2 0x04c
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL3 0x050
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL4 0x054
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL5 0x058
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL6 0x05c
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL7 0x060
|
||||
#define QPHY_V4_PCS_INSIG_SW_CTRL8 0x064
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL1 0x068
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL2 0x06c
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL3 0x070
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL4 0x074
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL5 0x078
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL7 0x07c
|
||||
#define QPHY_V4_PCS_INSIG_MX_CTRL8 0x080
|
||||
#define QPHY_V4_PCS_OUTSIG_SW_CTRL1 0x084
|
||||
#define QPHY_V4_PCS_OUTSIG_MX_CTRL1 0x088
|
||||
#define QPHY_V4_PCS_CLAMP_ENABLE 0x08c
|
||||
#define QPHY_V4_PCS_POWER_STATE_CONFIG1 0x090
|
||||
#define QPHY_V4_PCS_POWER_STATE_CONFIG2 0x094
|
||||
#define QPHY_V4_PCS_FLL_CNTRL1 0x098
|
||||
#define QPHY_V4_PCS_FLL_CNTRL2 0x09c
|
||||
#define QPHY_V4_PCS_FLL_CNT_VAL_L 0x0a0
|
||||
#define QPHY_V4_PCS_FLL_CNT_VAL_H_TOL 0x0a4
|
||||
#define QPHY_V4_PCS_FLL_MAN_CODE 0x0a8
|
||||
#define QPHY_V4_PCS_TEST_CONTROL1 0x0ac
|
||||
#define QPHY_V4_PCS_TEST_CONTROL2 0x0b0
|
||||
#define QPHY_V4_PCS_TEST_CONTROL3 0x0b4
|
||||
#define QPHY_V4_PCS_TEST_CONTROL4 0x0b8
|
||||
#define QPHY_V4_PCS_TEST_CONTROL5 0x0bc
|
||||
#define QPHY_V4_PCS_TEST_CONTROL6 0x0c0
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG1 0x0c4
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG2 0x0c8
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG3 0x0cc
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG4 0x0d0
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG5 0x0d4
|
||||
#define QPHY_V4_PCS_LOCK_DETECT_CONFIG6 0x0d8
|
||||
#define QPHY_V4_PCS_REFGEN_REQ_CONFIG1 0x0dc
|
||||
#define QPHY_V4_PCS_REFGEN_REQ_CONFIG2 0x0e0
|
||||
#define QPHY_V4_PCS_REFGEN_REQ_CONFIG3 0x0e4
|
||||
#define QPHY_V4_PCS_BIST_CTRL 0x0e8
|
||||
#define QPHY_V4_PCS_PRBS_POLY0 0x0ec
|
||||
#define QPHY_V4_PCS_PRBS_POLY1 0x0f0
|
||||
#define QPHY_V4_PCS_FIXED_PAT0 0x0f4
|
||||
#define QPHY_V4_PCS_FIXED_PAT1 0x0f8
|
||||
#define QPHY_V4_PCS_FIXED_PAT2 0x0fc
|
||||
#define QPHY_V4_PCS_FIXED_PAT3 0x100
|
||||
#define QPHY_V4_PCS_FIXED_PAT4 0x104
|
||||
#define QPHY_V4_PCS_FIXED_PAT5 0x108
|
||||
#define QPHY_V4_PCS_FIXED_PAT6 0x10c
|
||||
#define QPHY_V4_PCS_FIXED_PAT7 0x110
|
||||
#define QPHY_V4_PCS_FIXED_PAT8 0x114
|
||||
#define QPHY_V4_PCS_FIXED_PAT9 0x118
|
||||
#define QPHY_V4_PCS_FIXED_PAT10 0x11c
|
||||
#define QPHY_V4_PCS_FIXED_PAT11 0x120
|
||||
#define QPHY_V4_PCS_FIXED_PAT12 0x124
|
||||
#define QPHY_V4_PCS_FIXED_PAT13 0x128
|
||||
#define QPHY_V4_PCS_FIXED_PAT14 0x12c
|
||||
#define QPHY_V4_PCS_FIXED_PAT15 0x130
|
||||
#define QPHY_V4_PCS_TXMGN_CONFIG 0x134
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V0 0x138
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V1 0x13c
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V2 0x140
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V3 0x144
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V4 0x148
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V0_RS 0x14c
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V1_RS 0x150
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V2_RS 0x154
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V3_RS 0x158
|
||||
#define QPHY_V4_PCS_G12S1_TXMGN_V4_RS 0x15c
|
||||
#define QPHY_V4_PCS_G3S2_TXMGN_MAIN 0x160
|
||||
#define QPHY_V4_PCS_G3S2_TXMGN_MAIN_RS 0x164
|
||||
#define QPHY_V4_PCS_G12S1_TXDEEMPH_M6DB 0x168
|
||||
#define QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB 0x16c
|
||||
#define QPHY_V4_PCS_G3S2_PRE_GAIN 0x170
|
||||
#define QPHY_V4_PCS_G3S2_POST_GAIN 0x174
|
||||
#define QPHY_V4_PCS_G3S2_PRE_POST_OFFSET 0x178
|
||||
#define QPHY_V4_PCS_G3S2_PRE_GAIN_RS 0x17c
|
||||
#define QPHY_V4_PCS_G3S2_POST_GAIN_RS 0x180
|
||||
#define QPHY_V4_PCS_G3S2_PRE_POST_OFFSET_RS 0x184
|
||||
#define QPHY_V4_PCS_RX_SIGDET_LVL 0x188
|
||||
#define QPHY_V4_PCS_RX_SIGDET_DTCT_CNTRL 0x18c
|
||||
#define QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L 0x190
|
||||
#define QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H 0x194
|
||||
#define QPHY_V4_PCS_RATE_SLEW_CNTRL1 0x198
|
||||
#define QPHY_V4_PCS_RATE_SLEW_CNTRL2 0x19c
|
||||
#define QPHY_V4_PCS_PWRUP_RESET_DLY_TIME_AUXCLK 0x1a0
|
||||
#define QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L 0x1a4
|
||||
#define QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_H 0x1a8
|
||||
#define QPHY_V4_PCS_TSYNC_RSYNC_TIME 0x1ac
|
||||
#define QPHY_V4_PCS_CDR_RESET_TIME 0x1b0
|
||||
#define QPHY_V4_PCS_TSYNC_DLY_TIME 0x1b4
|
||||
#define QPHY_V4_PCS_ELECIDLE_DLY_SEL 0x1b8
|
||||
#define QPHY_V4_PCS_CMN_ACK_OUT_SEL 0x1bc
|
||||
#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG1 0x1c0
|
||||
#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG2 0x1c4
|
||||
#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG3 0x1c8
|
||||
#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG4 0x1cc
|
||||
#define QPHY_V4_PCS_PCS_TX_RX_CONFIG 0x1d0
|
||||
#define QPHY_V4_PCS_RX_IDLE_DTCT_CNTRL 0x1d4
|
||||
#define QPHY_V4_PCS_RX_DCC_CAL_CONFIG 0x1d8
|
||||
#define QPHY_V4_PCS_EQ_CONFIG1 0x1dc
|
||||
#define QPHY_V4_PCS_EQ_CONFIG2 0x1e0
|
||||
#define QPHY_V4_PCS_EQ_CONFIG3 0x1e4
|
||||
#define QPHY_V4_PCS_EQ_CONFIG4 0x1e8
|
||||
#define QPHY_V4_PCS_EQ_CONFIG5 0x1ec
|
||||
|
||||
/* Only for QMP V4 PHY - PCS_MISC registers */
|
||||
#define QPHY_V4_PCS_MISC_TYPEC_CTRL 0x00
|
||||
#define QPHY_V4_PCS_MISC_TYPEC_PWRDN_CTRL 0x04
|
||||
#define QPHY_V4_PCS_MISC_PCS_MISC_CONFIG1 0x08
|
||||
#define QPHY_V4_PCS_MISC_CLAMP_ENABLE 0x0c
|
||||
#define QPHY_V4_PCS_MISC_TYPEC_STATUS 0x10
|
||||
#define QPHY_V4_PCS_MISC_PLACEHOLDER_STATUS 0x14
|
||||
|
||||
/* Only for QMP V4 PHY - PCS_PCIE registers */
|
||||
#define QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2 0x0c
|
||||
#define QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4 0x14
|
||||
#define QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x1c
|
||||
#define QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x40
|
||||
#define QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x48
|
||||
#define QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1 0x50
|
||||
#define QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS 0x90
|
||||
#define QPHY_V4_PCS_PCIE_EQ_CONFIG2 0xa4
|
||||
#define QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE 0xb4
|
||||
#define QPHY_V4_PCS_PCIE_PRESET_P10_PRE 0xbc
|
||||
#define QPHY_V4_PCS_PCIE_PRESET_P10_POST 0xe0
|
||||
|
||||
#endif
|
459
src/soc/qualcomm/common/pcie_common.c
Normal file
459
src/soc/qualcomm/common/pcie_common.c
Normal file
@ -0,0 +1,459 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <boot/coreboot_tables.h>
|
||||
#include <console/console.h>
|
||||
#include <delay.h>
|
||||
#include <device/device.h>
|
||||
#include <device/mmio.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_def.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <gpio.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/qcom_qmp_phy.h>
|
||||
#include <soc/pcie.h>
|
||||
#include <timer.h>
|
||||
|
||||
#define ROOT_PORT_BDF 0x0
|
||||
#define ATU_CTRL2 PCIE_ATU_UNR_REGION_CTRL2
|
||||
|
||||
static struct qcom_pcie_cntlr_t qcom_pcie_cfg;
|
||||
|
||||
static inline void dw_pcie_dbi_rd_wr(bool enable)
|
||||
{
|
||||
uint32_t val;
|
||||
pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
|
||||
|
||||
val = read32(pcierc->dbi_base + PCIE_DBI_MISC_CONTROL_1_OFF);
|
||||
|
||||
if (enable)
|
||||
val |= PCIE_DBI_RO_WR_EN;
|
||||
else
|
||||
val &= ~PCIE_DBI_RO_WR_EN;
|
||||
|
||||
write32(pcierc->dbi_base + PCIE_DBI_MISC_CONTROL_1_OFF, val);
|
||||
}
|
||||
|
||||
static void dw_pcie_writel_iatu(unsigned int index, uint32_t reg, uint32_t val)
|
||||
{
|
||||
pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
|
||||
unsigned int offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
|
||||
|
||||
write32(pcierc->atu_base + offset + reg, val);
|
||||
}
|
||||
|
||||
static uint32_t dw_pcie_readl_iatu(unsigned int index, uint32_t reg)
|
||||
{
|
||||
pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
|
||||
unsigned int offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
|
||||
|
||||
return read32(pcierc->atu_base + offset + reg);
|
||||
}
|
||||
|
||||
static void qcom_dw_pcie_prog_outbound_atu(unsigned int index,
|
||||
unsigned int type, uint64_t cpu_addr,
|
||||
uint64_t pcie_addr, uint32_t size)
|
||||
{
|
||||
dw_pcie_writel_iatu(index, PCIE_ATU_UNR_LOWER_BASE, lower_32_bits(cpu_addr));
|
||||
dw_pcie_writel_iatu(index, PCIE_ATU_UNR_UPPER_BASE, upper_32_bits(cpu_addr));
|
||||
dw_pcie_writel_iatu(index, PCIE_ATU_UNR_LIMIT, lower_32_bits(cpu_addr + size - 1));
|
||||
dw_pcie_writel_iatu(index, PCIE_ATU_UNR_LOWER_TARGET, lower_32_bits(pcie_addr));
|
||||
dw_pcie_writel_iatu(index, PCIE_ATU_UNR_UPPER_TARGET, upper_32_bits(pcie_addr));
|
||||
dw_pcie_writel_iatu(index, PCIE_ATU_UNR_REGION_CTRL1, type);
|
||||
dw_pcie_writel_iatu(index, PCIE_ATU_UNR_REGION_CTRL2, PCIE_ATU_ENABLE);
|
||||
|
||||
/* Ensure ATU enable takes effect before any subsequent config access */
|
||||
if (retry(LINK_WAIT_MAX_IATU_RETRIES,
|
||||
(dw_pcie_readl_iatu(index, ATU_CTRL2) & PCIE_ATU_ENABLE),
|
||||
udelay(LINK_WAIT_IATU)))
|
||||
return;
|
||||
|
||||
printk(BIOS_ERR, "PCIe o/b iATU couldn't be enabled after 5ms\n");
|
||||
}
|
||||
|
||||
static void qcom_pcie_configure_gpios(pcie_cntlr_cfg_t *cfg)
|
||||
{
|
||||
gpio_configure(cfg->perst, 0, GPIO_NO_PULL, GPIO_16MA, GPIO_OUTPUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_dw_pcie_configure() - Configure link capabilities and speed
|
||||
*
|
||||
* Configure the link capabilities and speed in the PCIe root complex.
|
||||
*/
|
||||
static void qcom_dw_pcie_configure(uint32_t cap_speed)
|
||||
{
|
||||
pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
|
||||
|
||||
dw_pcie_dbi_rd_wr(true);
|
||||
|
||||
clrsetbits32(pcierc->dbi_base + PCIE_LINK_CAPABILITY,
|
||||
TARGET_LINK_SPEED_MASK, cap_speed);
|
||||
|
||||
clrsetbits32(pcierc->dbi_base + PCIE_LINK_CTL_2,
|
||||
TARGET_LINK_SPEED_MASK, cap_speed);
|
||||
|
||||
dw_pcie_dbi_rd_wr(false);
|
||||
printk(BIOS_INFO, "PCIe Link speed configured in Gen %d\n", cap_speed);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_pcie_link_up() - Return the link state
|
||||
*
|
||||
* Return: true for active link and false for no link
|
||||
*/
|
||||
static bool is_pcie_link_up(struct qcom_pcie_cntlr_t *pci)
|
||||
{
|
||||
/* Read link status register */
|
||||
return !!(read32(pci->cntlr_cfg->elbi + PCIE3X2_ELBI_SYS_STTS) & XMLH_LINK_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* wait_link_up() - Wait for the link to come up
|
||||
*
|
||||
* Return: true for active line and false for no link (timeout)
|
||||
*/
|
||||
static bool wait_link_up(struct qcom_pcie_cntlr_t *pci)
|
||||
{
|
||||
/* Check if the link is up or not */
|
||||
if (retry(LINK_WAIT_MAX_RETRIES, is_pcie_link_up(pci), mdelay(PCIE_LINK_UP_MS)))
|
||||
return true;
|
||||
|
||||
printk(BIOS_ERR, "PCIe link is not up even after 1sec\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum cb_err qcom_pcie_dw_link_up(struct qcom_pcie_cntlr_t *pcie)
|
||||
{
|
||||
if (is_pcie_link_up(pcie)) {
|
||||
printk(BIOS_INFO, "PCIe Link is already up\n");
|
||||
return CB_SUCCESS;
|
||||
}
|
||||
|
||||
/* DW pre link configurations */
|
||||
qcom_dw_pcie_configure(LINK_SPEED_GEN_2);
|
||||
|
||||
/* enable link training */
|
||||
setbits32(pcie->cntlr_cfg->parf + PCIE_PARF_LTSSM, LTSSM_EN);
|
||||
|
||||
/* Check that link was established */
|
||||
if (wait_link_up(pcie)) {
|
||||
printk(BIOS_INFO, "PCIe link is up\n");
|
||||
return CB_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Link can be established in Gen 1 as it failed to establish in Gen2.
|
||||
* So allow some time to do it.
|
||||
*/
|
||||
udelay(100);
|
||||
|
||||
return CB_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns root port config space address or endpoint config space address.
|
||||
* For endpoint config address, mapping would be done with ATU.
|
||||
*/
|
||||
static void *qcom_dw_pcie_get_config_addr(struct qcom_pcie_cntlr_t *pcierc,
|
||||
pci_devfn_t dev)
|
||||
{
|
||||
unsigned int atu_type, cfg_size;
|
||||
void *cfg_address;
|
||||
uint32_t bus, busdev, devfn;
|
||||
pcie_cntlr_cfg_t *cntlr = pcierc->cntlr_cfg;
|
||||
bus = PCI_DEV2SEGBUS(dev);
|
||||
devfn = PCI_DEV2DEVFN(dev);
|
||||
|
||||
busdev = PCIE_ATU_BUS(bus) |
|
||||
PCIE_ATU_DEV(PCI_SLOT(devfn)) |
|
||||
PCIE_ATU_FUNC(PCI_FUNC(devfn));
|
||||
|
||||
/* Accessing root port configuration space */
|
||||
if (!bus && !devfn) {
|
||||
cfg_address = pcierc->cntlr_cfg->dbi_base;
|
||||
return cfg_address;
|
||||
}
|
||||
|
||||
/* For local bus use CFG0 type */
|
||||
atu_type = (bus == 1) ? PCIE_ATU_TYPE_CFG0 : PCIE_ATU_TYPE_CFG1;
|
||||
|
||||
cfg_address = cntlr->cfg_base + (cntlr->cfg_size * devfn);
|
||||
cfg_size = cntlr->cfg_size;
|
||||
|
||||
qcom_dw_pcie_prog_outbound_atu(PCIE_ATU_REGION_INDEX1, atu_type,
|
||||
(uint64_t)cfg_address, busdev, cfg_size);
|
||||
return cfg_address;
|
||||
}
|
||||
|
||||
static void qcom_dw_pcie_setup_rc(struct qcom_pcie_cntlr_t *pcie)
|
||||
{
|
||||
uint32_t val;
|
||||
pcie_cntlr_cfg_t *pcierc = pcie->cntlr_cfg;
|
||||
/*
|
||||
* Enable DBI read-only registers for writing/updating configuration.
|
||||
* Write permission gets disabled towards the end of this function.
|
||||
*/
|
||||
dw_pcie_dbi_rd_wr(true);
|
||||
|
||||
val = read32(pcierc->dbi_base + PCIE_PORT_LINK_CONTROL);
|
||||
/* Set the number of lanes */
|
||||
val &= ~PORT_LINK_MODE_MASK;
|
||||
|
||||
switch (pcierc->lanes) {
|
||||
case 1:
|
||||
val |= PORT_LINK_MODE_1_LANES;
|
||||
break;
|
||||
case 2:
|
||||
val |= PORT_LINK_MODE_2_LANES;
|
||||
break;
|
||||
case 4:
|
||||
val |= PORT_LINK_MODE_4_LANES;
|
||||
break;
|
||||
case 8:
|
||||
val |= PORT_LINK_MODE_8_LANES;
|
||||
break;
|
||||
default:
|
||||
printk(BIOS_INFO, "PCIe num-lanes %u: invalid value\n",
|
||||
pcierc->lanes);
|
||||
return;
|
||||
}
|
||||
|
||||
write32(pcierc->dbi_base + PCIE_PORT_LINK_CONTROL, val);
|
||||
|
||||
/* Set link width speed control register */
|
||||
val = read32(pcierc->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
|
||||
val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
|
||||
|
||||
switch (pcierc->lanes) {
|
||||
case 1:
|
||||
val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
|
||||
break;
|
||||
case 2:
|
||||
val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
|
||||
break;
|
||||
case 4:
|
||||
val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
|
||||
break;
|
||||
case 8:
|
||||
val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
|
||||
break;
|
||||
default:
|
||||
printk(BIOS_INFO, "PCIe invalid lanes option\n");
|
||||
return;
|
||||
}
|
||||
|
||||
write32(pcierc->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL, val);
|
||||
|
||||
/* Setup bus numbers */
|
||||
clrsetbits32(pcierc->dbi_base + PCI_PRIMARY_BUS, TYPE1_HDR_BUS_NUM_MASK,
|
||||
ROOT_PORT_BUS_NUM);
|
||||
|
||||
/* Disable SMMU */
|
||||
write32(pcierc->parf + PCIE_PARF_BDF_TO_SID_CFG, BDF_TO_SID_BYPASS);
|
||||
|
||||
/* Configure ATU for outbound accesses */
|
||||
qcom_dw_pcie_prog_outbound_atu(PCIE_ATU_REGION_INDEX0,
|
||||
PCIE_ATU_TYPE_MEM,
|
||||
pcierc->mem.phys_start,
|
||||
ROOT_PORT_BDF, pcierc->mem.size);
|
||||
|
||||
/* Program correct class for RC */
|
||||
write16(pcierc->dbi_base + PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
|
||||
|
||||
/* Disable write permission right after the update */
|
||||
dw_pcie_dbi_rd_wr(false);
|
||||
}
|
||||
|
||||
static void qcom_qmp_phy_config_lane(void *base, const struct qcom_qmp_phy_init_tbl tbl[],
|
||||
unsigned int num, uint8_t ln_mask)
|
||||
{
|
||||
unsigned int i;
|
||||
const struct qcom_qmp_phy_init_tbl *t = tbl;
|
||||
|
||||
for (i = 0; i < num; i++, t++) {
|
||||
if (!(t->lane_mask & ln_mask))
|
||||
continue;
|
||||
write32(base + t->offset, t->val);
|
||||
}
|
||||
}
|
||||
|
||||
static void qcom_qmp_phy_configure(void *base, const struct qcom_qmp_phy_init_tbl tbl[],
|
||||
unsigned int num)
|
||||
{
|
||||
qcom_qmp_phy_config_lane(base, tbl, num, 0xff);
|
||||
}
|
||||
|
||||
static enum cb_err qcom_qmp_phy_power_on(pcie_qmp_phy_cfg_t *qphy)
|
||||
{
|
||||
uint64_t lock_us;
|
||||
|
||||
/* Release powerdown mode and allow endpoint refclk drive */
|
||||
write32(qphy->pcs + QPHY_PCS_PWR_DWN_CNTRL, SW_PWRDN | REFCLK_DRV_DSBL);
|
||||
|
||||
/* Serdes configuration */
|
||||
qcom_qmp_phy_configure(qphy->serdes, qphy->serdes_tbl, qphy->serdes_tbl_num);
|
||||
|
||||
/* Tx, Rx, and PCS configurations */
|
||||
qcom_qmp_phy_config_lane(qphy->tx0, qphy->tx_tbl, qphy->tx_tbl_num, 1);
|
||||
qcom_qmp_phy_config_lane(qphy->tx0, qphy->tx_tbl_sec, qphy->tx_tbl_num_sec, 1);
|
||||
qcom_qmp_phy_config_lane(qphy->tx1, qphy->tx_tbl, qphy->tx_tbl_num, 2);
|
||||
qcom_qmp_phy_config_lane(qphy->tx1, qphy->tx_tbl_sec, qphy->tx_tbl_num_sec, 2);
|
||||
qcom_qmp_phy_config_lane(qphy->rx0, qphy->rx_tbl, qphy->rx_tbl_num, 1);
|
||||
qcom_qmp_phy_config_lane(qphy->rx0, qphy->rx_tbl_sec, qphy->rx_tbl_num_sec, 1);
|
||||
qcom_qmp_phy_config_lane(qphy->rx1, qphy->rx_tbl, qphy->rx_tbl_num, 2);
|
||||
qcom_qmp_phy_config_lane(qphy->rx1, qphy->rx_tbl_sec, qphy->rx_tbl_num_sec, 2);
|
||||
qcom_qmp_phy_configure(qphy->pcs, qphy->pcs_tbl, qphy->pcs_tbl_num);
|
||||
qcom_qmp_phy_configure(qphy->pcs, qphy->pcs_tbl_sec, qphy->pcs_tbl_num_sec);
|
||||
qcom_qmp_phy_configure(qphy->pcs_misc, qphy->pcs_misc_tbl, qphy->pcs_misc_tbl_num);
|
||||
qcom_qmp_phy_configure(qphy->pcs_misc, qphy->pcs_misc_tbl_sec, qphy->pcs_tbl_num_sec);
|
||||
|
||||
/* Release software reset of PCS/Serdes */
|
||||
clrbits32(qphy->pcs + QPHY_SW_RESET, SW_RESET);
|
||||
|
||||
/* start PCS/Serdes to operation mode */
|
||||
write32(qphy->pcs + QPHY_START_CTRL, PCS_START | SERDES_START);
|
||||
|
||||
/*
|
||||
* Wait for PHY initialization to be done
|
||||
* PCS_STATUS: wait for 1ms for PHY STATUS bit to be set
|
||||
*/
|
||||
lock_us = wait_us(1000, !(read32(qphy->qmp_phy_base + QPHY_PCS_STATUS) & PHY_STATUS));
|
||||
if (!lock_us) {
|
||||
printk(BIOS_ERR, "PCIe QMP PHY PLL failed to lock in 1ms\n");
|
||||
return CB_ERR;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "PCIe QPHY Initialized took %lldus\n", lock_us);
|
||||
|
||||
qcom_dw_pcie_enable_pipe_clock();
|
||||
|
||||
return CB_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the PCIe PHY core.
|
||||
* Allow 100us delay to ensure reset is asserted.
|
||||
*/
|
||||
static void qcom_qmp_reset_phy(struct qcom_pcie_cntlr_t *pcie)
|
||||
{
|
||||
clock_reset_bcr(pcie->cntlr_cfg->qmp_phy_bcr, 1);
|
||||
udelay(100);
|
||||
clock_reset_bcr(pcie->cntlr_cfg->qmp_phy_bcr, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the PCIe controller core.
|
||||
* Allow 100us delay to ensure reset is asserted.
|
||||
*/
|
||||
static void qcom_dw_pcie_reset_core(struct qcom_pcie_cntlr_t *pcie)
|
||||
{
|
||||
clock_reset_bcr(pcie->cntlr_cfg->pcie_bcr, 1);
|
||||
udelay(100);
|
||||
clock_reset_bcr(pcie->cntlr_cfg->pcie_bcr, 0);
|
||||
}
|
||||
|
||||
static enum cb_err qcom_dw_pcie_enable(struct qcom_pcie_cntlr_t *pcie)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pcie_cntlr_cfg_t *pcierc = pcie->cntlr_cfg;
|
||||
pcie_qmp_phy_cfg_t *qmp_phy = pcie->qmp_phy_cfg;
|
||||
|
||||
/* assert PCIe reset link to keep EP in reset */
|
||||
gpio_set(pcierc->perst, 0);
|
||||
|
||||
/* Enable PCIe controller and SoC specific clocks */
|
||||
ret = qcom_dw_pcie_enable_clock();
|
||||
if (ret) {
|
||||
printk(BIOS_ERR, "Enable PCIe clocks failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset the controller */
|
||||
qcom_dw_pcie_reset_core(pcie);
|
||||
|
||||
/* configure PCIe to RC mode */
|
||||
write32(pcierc->parf + PCIE_PARF_DEVICE_TYPE, DEVICE_TYPE_RC);
|
||||
|
||||
/* Power on the PHY */
|
||||
clrbits32(pcierc->parf + PCIE_PARF_PHY_CTRL, PHY_PWR_DOWN);
|
||||
|
||||
/* MAC PHY_POWERDOWN MUX DISABLE */
|
||||
clrbits32(pcierc->parf + PCIE_PARF_SYS_CTRL, MAC_PHY_PWRDOWN_MUX_EN);
|
||||
|
||||
/* Bypass MHI as its not needed */
|
||||
setbits32(pcierc->parf + PCIE_PARF_MHI_CLOCK_RESET_CTRL, MHI_BYPASS);
|
||||
|
||||
qcom_qmp_reset_phy(pcie);
|
||||
|
||||
/* Initialize QMP PHY */
|
||||
ret = qcom_qmp_phy_power_on(qmp_phy);
|
||||
if (ret) {
|
||||
printk(BIOS_ERR, "PCIe PHY init failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
qcom_dw_pcie_setup_rc(pcie);
|
||||
|
||||
/* de-assert PCIe reset link to bring EP out of reset */
|
||||
gpio_set(pcierc->perst, 1);
|
||||
|
||||
/* establisth the link */
|
||||
ret = qcom_pcie_dw_link_up(pcie);
|
||||
if (ret) {
|
||||
printk(BIOS_ERR, "PCIe Link init failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return CB_SUCCESS;
|
||||
}
|
||||
|
||||
/* map_bus function for mapping pcie_s_{read/write}_configXX() functions */
|
||||
volatile union pci_bank *pci_map_bus(pci_devfn_t dev)
|
||||
{
|
||||
void *config_addr = NULL;
|
||||
|
||||
config_addr = qcom_dw_pcie_get_config_addr(&qcom_pcie_cfg, dev);
|
||||
return (void *)config_addr;
|
||||
}
|
||||
|
||||
/* PCI domain ops read_resources callback */
|
||||
void qcom_pci_domain_read_resources(struct device *dev)
|
||||
{
|
||||
struct resource *res;
|
||||
pcie_cntlr_cfg_t *pcierc = qcom_pcie_cfg.cntlr_cfg;
|
||||
|
||||
/* Initialize the system-wide I/O space constraints. */
|
||||
res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
|
||||
res->base = pcierc->io.phys_start;
|
||||
res->limit = pcierc->io.size - 1;
|
||||
res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
|
||||
|
||||
/* Initialize the system-wide memory resources constraints. */
|
||||
res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
|
||||
res->base = pcierc->mem.phys_start;
|
||||
res->limit = pcierc->mem.size - 1;
|
||||
res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
|
||||
}
|
||||
|
||||
/* PCI domain ops enable callback */
|
||||
void qcom_setup_pcie_host(struct device *dev)
|
||||
{
|
||||
gcom_pcie_get_config(&qcom_pcie_cfg);
|
||||
|
||||
/* Ensure PCIe endpoints are powered-on before initiating PCIe link training */
|
||||
gcom_pcie_power_on_ep();
|
||||
|
||||
printk(BIOS_INFO, "Setup PCIe in RC mode\n");
|
||||
|
||||
/* Configure PERST gpio */
|
||||
qcom_pcie_configure_gpios(qcom_pcie_cfg.cntlr_cfg);
|
||||
|
||||
if (!qcom_dw_pcie_enable(&qcom_pcie_cfg))
|
||||
printk(BIOS_NOTICE, "PCIe enumerated succussfully..\n");
|
||||
else
|
||||
printk(BIOS_EMERG, "Failed to enable PCIe\n");
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user