Loading drivers/pci/controller/pci-msm.c +83 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,7 @@ #define REFCLK_STABILIZATION_DELAY_US_MAX (1005) #define LINK_UP_TIMEOUT_US_MIN (5000) #define LINK_UP_TIMEOUT_US_MAX (5100) #define LINK_CHECK_COUNT_MAX (20) #define LINK_UP_CHECK_MAX_COUNT (20) #define EP_UP_TIMEOUT_US_MIN (1000) #define EP_UP_TIMEOUT_US_MAX (1005) Loading Loading @@ -6618,6 +6619,88 @@ static int msm_pcie_set_link_width(struct msm_pcie_dev_t *pcie_dev, return 0; } int msm_pcie_dsp_link_control(struct pci_dev *pci_dev, bool link_enable) { int ret = 0; struct pci_dev *dsp_dev = NULL; u16 link_control = 0; u16 link_status = 0; u32 link_capability = 0; int link_check_count = 0; bool link_trained = false; struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(pci_dev->bus); if (!pcie_dev->power_on) return 0; dsp_dev = pci_dev->bus->self; if (pci_pcie_type(dsp_dev) != PCI_EXP_TYPE_DOWNSTREAM) { PCIE_DBG(pcie_dev, "PCIe: RC%d: no DSP<->EP link under this RC\n", pcie_dev->rc_idx); return 0; } pci_read_config_dword(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKCAP, &link_capability); pci_read_config_word(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKCTL, &link_control); if (link_enable) { link_control &= ~PCI_EXP_LNKCTL_LD; pci_write_config_word(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKCTL, link_control); PCIE_DBG(pcie_dev, "PCIe: RC%d: DSP<->EP Link is enabled\n", pcie_dev->rc_idx); /* Wait for up to 100ms for the link to come up */ do { usleep_range(LINK_UP_TIMEOUT_US_MIN, LINK_UP_TIMEOUT_US_MAX); pci_read_config_word(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKSTA, &link_status); if (link_capability & PCI_EXP_LNKCAP_DLLLARC) link_trained = (!(link_status & PCI_EXP_LNKSTA_LT)) && (link_status & PCI_EXP_LNKSTA_DLLLA); else link_trained = !(link_status & PCI_EXP_LNKSTA_LT); if (link_trained) break; } while (link_check_count++ < LINK_CHECK_COUNT_MAX); if (link_trained) { PCIE_DBG(pcie_dev, "PCIe: RC%d: DSP<->EP link status: 0x%04x\n", pcie_dev->rc_idx, link_status); PCIE_DBG(pcie_dev, "PCIe: RC%d: DSP<->EP Link is up after %d checkings\n", pcie_dev->rc_idx, link_check_count); } else { PCIE_DBG(pcie_dev, "DSP<->EP link initialization failed\n"); ret = MSM_PCIE_ERROR; } } else { link_control |= PCI_EXP_LNKCTL_LD; pci_write_config_word(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKCTL, link_control); PCIE_DBG(pcie_dev, "PCIe: RC%d: DSP<->EP Link is disabled\n", pcie_dev->rc_idx); } return ret; } EXPORT_SYMBOL(msm_pcie_dsp_link_control); void msm_pcie_allow_l1(struct pci_dev *pci_dev) { struct pci_dev *root_pci_dev; Loading include/linux/msm_pcie.h +17 −0 Original line number Diff line number Diff line Loading @@ -212,6 +212,17 @@ int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base, */ int msm_pcie_reg_dump(struct pci_dev *pci_dev, u8 *buff, u32 len); /* * msm_pcie_dsp_link_control - enable/disable DSP link * @pci_dev: pci device structure, endpoint of this DSP * @link_enable true to enable, false to disable * * This function enable(include training)/disable link between PCIe * switch DSP and endpoint attached. * Return: 0 on success, negative value on error */ int msm_pcie_dsp_link_control(struct pci_dev *pci_dev, bool link_enable); #else /* !CONFIG_PCI_MSM */ static inline int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user, void *data, u32 options) Loading Loading @@ -269,6 +280,12 @@ static inline int msm_pcie_reg_dump(struct pci_dev *pci_dev, u8 *buff, u32 len) { return -ENODEV; } static inline int msm_pcie_dsp_link_control(struct pci_dev *pci_dev, bool link_enable) { return -ENODEV; } #endif /* CONFIG_PCI_MSM */ #endif /* __MSM_PCIE_H */ Loading
drivers/pci/controller/pci-msm.c +83 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,7 @@ #define REFCLK_STABILIZATION_DELAY_US_MAX (1005) #define LINK_UP_TIMEOUT_US_MIN (5000) #define LINK_UP_TIMEOUT_US_MAX (5100) #define LINK_CHECK_COUNT_MAX (20) #define LINK_UP_CHECK_MAX_COUNT (20) #define EP_UP_TIMEOUT_US_MIN (1000) #define EP_UP_TIMEOUT_US_MAX (1005) Loading Loading @@ -6618,6 +6619,88 @@ static int msm_pcie_set_link_width(struct msm_pcie_dev_t *pcie_dev, return 0; } int msm_pcie_dsp_link_control(struct pci_dev *pci_dev, bool link_enable) { int ret = 0; struct pci_dev *dsp_dev = NULL; u16 link_control = 0; u16 link_status = 0; u32 link_capability = 0; int link_check_count = 0; bool link_trained = false; struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(pci_dev->bus); if (!pcie_dev->power_on) return 0; dsp_dev = pci_dev->bus->self; if (pci_pcie_type(dsp_dev) != PCI_EXP_TYPE_DOWNSTREAM) { PCIE_DBG(pcie_dev, "PCIe: RC%d: no DSP<->EP link under this RC\n", pcie_dev->rc_idx); return 0; } pci_read_config_dword(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKCAP, &link_capability); pci_read_config_word(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKCTL, &link_control); if (link_enable) { link_control &= ~PCI_EXP_LNKCTL_LD; pci_write_config_word(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKCTL, link_control); PCIE_DBG(pcie_dev, "PCIe: RC%d: DSP<->EP Link is enabled\n", pcie_dev->rc_idx); /* Wait for up to 100ms for the link to come up */ do { usleep_range(LINK_UP_TIMEOUT_US_MIN, LINK_UP_TIMEOUT_US_MAX); pci_read_config_word(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKSTA, &link_status); if (link_capability & PCI_EXP_LNKCAP_DLLLARC) link_trained = (!(link_status & PCI_EXP_LNKSTA_LT)) && (link_status & PCI_EXP_LNKSTA_DLLLA); else link_trained = !(link_status & PCI_EXP_LNKSTA_LT); if (link_trained) break; } while (link_check_count++ < LINK_CHECK_COUNT_MAX); if (link_trained) { PCIE_DBG(pcie_dev, "PCIe: RC%d: DSP<->EP link status: 0x%04x\n", pcie_dev->rc_idx, link_status); PCIE_DBG(pcie_dev, "PCIe: RC%d: DSP<->EP Link is up after %d checkings\n", pcie_dev->rc_idx, link_check_count); } else { PCIE_DBG(pcie_dev, "DSP<->EP link initialization failed\n"); ret = MSM_PCIE_ERROR; } } else { link_control |= PCI_EXP_LNKCTL_LD; pci_write_config_word(dsp_dev, dsp_dev->pcie_cap + PCI_EXP_LNKCTL, link_control); PCIE_DBG(pcie_dev, "PCIe: RC%d: DSP<->EP Link is disabled\n", pcie_dev->rc_idx); } return ret; } EXPORT_SYMBOL(msm_pcie_dsp_link_control); void msm_pcie_allow_l1(struct pci_dev *pci_dev) { struct pci_dev *root_pci_dev; Loading
include/linux/msm_pcie.h +17 −0 Original line number Diff line number Diff line Loading @@ -212,6 +212,17 @@ int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base, */ int msm_pcie_reg_dump(struct pci_dev *pci_dev, u8 *buff, u32 len); /* * msm_pcie_dsp_link_control - enable/disable DSP link * @pci_dev: pci device structure, endpoint of this DSP * @link_enable true to enable, false to disable * * This function enable(include training)/disable link between PCIe * switch DSP and endpoint attached. * Return: 0 on success, negative value on error */ int msm_pcie_dsp_link_control(struct pci_dev *pci_dev, bool link_enable); #else /* !CONFIG_PCI_MSM */ static inline int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user, void *data, u32 options) Loading Loading @@ -269,6 +280,12 @@ static inline int msm_pcie_reg_dump(struct pci_dev *pci_dev, u8 *buff, u32 len) { return -ENODEV; } static inline int msm_pcie_dsp_link_control(struct pci_dev *pci_dev, bool link_enable) { return -ENODEV; } #endif /* CONFIG_PCI_MSM */ #endif /* __MSM_PCIE_H */