| .. | .. |
|---|
| 8 | 8 | * Author: Simon Xue <xxm@rock-chips.com> |
|---|
| 9 | 9 | */ |
|---|
| 10 | 10 | |
|---|
| 11 | +#include <dt-bindings/phy/phy.h> |
|---|
| 11 | 12 | #include <linux/clk.h> |
|---|
| 12 | 13 | #include <linux/delay.h> |
|---|
| 13 | 14 | #include <linux/fs.h> |
|---|
| .. | .. |
|---|
| 142 | 143 | #define PCIE_PL_ORDER_RULE_CTRL_OFF 0x8B4 |
|---|
| 143 | 144 | #define RK_PCIE_L2_TMOUT_US 5000 |
|---|
| 144 | 145 | #define RK_PCIE_HOTRESET_TMOUT_US 10000 |
|---|
| 146 | +#define RK_PCIE_ENUM_HW_RETRYIES 2 |
|---|
| 145 | 147 | |
|---|
| 146 | 148 | enum rk_pcie_ltssm_code { |
|---|
| 147 | 149 | S_L0 = 0x11, |
|---|
| .. | .. |
|---|
| 202 | 204 | }; |
|---|
| 203 | 205 | |
|---|
| 204 | 206 | #define to_rk_pcie(x) dev_get_drvdata((x)->dev) |
|---|
| 207 | +static int rk_pcie_disable_power(struct rk_pcie *rk_pcie); |
|---|
| 208 | +static int rk_pcie_enable_power(struct rk_pcie *rk_pcie); |
|---|
| 205 | 209 | |
|---|
| 206 | 210 | static int rk_pcie_read(void __iomem *addr, int size, u32 *val) |
|---|
| 207 | 211 | { |
|---|
| .. | .. |
|---|
| 702 | 706 | rk_pcie_writel_apb(rk_pcie, 0x0, 0xC000C); |
|---|
| 703 | 707 | } |
|---|
| 704 | 708 | |
|---|
| 705 | | -static int rk_pcie_link_up(struct dw_pcie *pci) |
|---|
| 706 | | -{ |
|---|
| 707 | | - struct rk_pcie *rk_pcie = to_rk_pcie(pci); |
|---|
| 708 | | - u32 val; |
|---|
| 709 | | - |
|---|
| 710 | | - if (rk_pcie->is_rk1808) { |
|---|
| 711 | | - val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_GENERAL_DEBUG); |
|---|
| 712 | | - if ((val & (PCIE_PHY_LINKUP | PCIE_DATA_LINKUP)) == 0x3) |
|---|
| 713 | | - return 1; |
|---|
| 714 | | - } else { |
|---|
| 715 | | - val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS); |
|---|
| 716 | | - if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000) |
|---|
| 717 | | - return 1; |
|---|
| 718 | | - } |
|---|
| 719 | | - |
|---|
| 720 | | - return 0; |
|---|
| 721 | | -} |
|---|
| 722 | | - |
|---|
| 723 | 709 | static void rk_pcie_enable_debug(struct rk_pcie *rk_pcie) |
|---|
| 724 | 710 | { |
|---|
| 725 | 711 | if (!IS_ENABLED(CONFIG_DEBUG_FS)) |
|---|
| .. | .. |
|---|
| 758 | 744 | int retries, power; |
|---|
| 759 | 745 | struct rk_pcie *rk_pcie = to_rk_pcie(pci); |
|---|
| 760 | 746 | bool std_rc = rk_pcie->mode == RK_PCIE_RC_TYPE && !rk_pcie->dma_obj; |
|---|
| 747 | + int hw_retries = 0; |
|---|
| 748 | + u32 ltssm; |
|---|
| 761 | 749 | |
|---|
| 762 | 750 | /* |
|---|
| 763 | 751 | * For standard RC, even if the link has been setup by firmware, |
|---|
| .. | .. |
|---|
| 769 | 757 | return 0; |
|---|
| 770 | 758 | } |
|---|
| 771 | 759 | |
|---|
| 772 | | - /* Rest the device */ |
|---|
| 773 | | - gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0); |
|---|
| 760 | + for (hw_retries = 0; hw_retries < RK_PCIE_ENUM_HW_RETRYIES; hw_retries++) { |
|---|
| 761 | + /* Rest the device */ |
|---|
| 762 | + gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0); |
|---|
| 774 | 763 | |
|---|
| 775 | | - rk_pcie_disable_ltssm(rk_pcie); |
|---|
| 776 | | - rk_pcie_link_status_clear(rk_pcie); |
|---|
| 777 | | - rk_pcie_enable_debug(rk_pcie); |
|---|
| 764 | + rk_pcie_disable_ltssm(rk_pcie); |
|---|
| 765 | + rk_pcie_link_status_clear(rk_pcie); |
|---|
| 766 | + rk_pcie_enable_debug(rk_pcie); |
|---|
| 778 | 767 | |
|---|
| 779 | | - /* Enable client reset or link down interrupt */ |
|---|
| 780 | | - rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0x40000); |
|---|
| 768 | + /* Enable client reset or link down interrupt */ |
|---|
| 769 | + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0x40000); |
|---|
| 781 | 770 | |
|---|
| 782 | | - /* Enable LTSSM */ |
|---|
| 783 | | - rk_pcie_enable_ltssm(rk_pcie); |
|---|
| 771 | + /* Enable LTSSM */ |
|---|
| 772 | + rk_pcie_enable_ltssm(rk_pcie); |
|---|
| 784 | 773 | |
|---|
| 785 | | - /* |
|---|
| 786 | | - * In resume routine, function devices' resume function must be late after |
|---|
| 787 | | - * controllers'. Some devices, such as Wi-Fi, need special IO setting before |
|---|
| 788 | | - * finishing training. So there must be timeout here. These kinds of devices |
|---|
| 789 | | - * need rescan devices by its driver when used. So no need to waste time waiting |
|---|
| 790 | | - * for training pass. |
|---|
| 791 | | - */ |
|---|
| 792 | | - if (rk_pcie->in_suspend && rk_pcie->skip_scan_in_resume) { |
|---|
| 793 | | - rfkill_get_wifi_power_state(&power); |
|---|
| 794 | | - if (!power) { |
|---|
| 795 | | - gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1); |
|---|
| 796 | | - return 0; |
|---|
| 797 | | - } |
|---|
| 798 | | - } |
|---|
| 799 | | - |
|---|
| 800 | | - /* |
|---|
| 801 | | - * PCIe requires the refclk to be stable for 100µs prior to releasing |
|---|
| 802 | | - * PERST and T_PVPERL (Power stable to PERST# inactive) should be a |
|---|
| 803 | | - * minimum of 100ms. See table 2-4 in section 2.6.2 AC, the PCI Express |
|---|
| 804 | | - * Card Electromechanical Specification 3.0. So 100ms in total is the min |
|---|
| 805 | | - * requuirement here. We add a 200ms by default for sake of hoping everthings |
|---|
| 806 | | - * work fine. If it doesn't, please add more in DT node by add rockchip,perst-inactive-ms. |
|---|
| 807 | | - */ |
|---|
| 808 | | - msleep(rk_pcie->perst_inactive_ms); |
|---|
| 809 | | - gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1); |
|---|
| 810 | | - |
|---|
| 811 | | - /* |
|---|
| 812 | | - * Add this 1ms delay because we observe link is always up stably after it and |
|---|
| 813 | | - * could help us save 20ms for scanning devices. |
|---|
| 814 | | - */ |
|---|
| 815 | | - usleep_range(1000, 1100); |
|---|
| 816 | | - |
|---|
| 817 | | - for (retries = 0; retries < 100; retries++) { |
|---|
| 818 | | - if (dw_pcie_link_up(pci)) { |
|---|
| 819 | | - /* |
|---|
| 820 | | - * We may be here in case of L0 in Gen1. But if EP is capable |
|---|
| 821 | | - * of Gen2 or Gen3, Gen switch may happen just in this time, but |
|---|
| 822 | | - * we keep on accessing devices in unstable link status. Given |
|---|
| 823 | | - * that LTSSM max timeout is 24ms per period, we can wait a bit |
|---|
| 824 | | - * more for Gen switch. |
|---|
| 825 | | - */ |
|---|
| 826 | | - msleep(50); |
|---|
| 827 | | - /* In case link drop after linkup, double check it */ |
|---|
| 828 | | - if (dw_pcie_link_up(pci)) { |
|---|
| 829 | | - dev_info(pci->dev, "PCIe Link up, LTSSM is 0x%x\n", |
|---|
| 830 | | - rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS)); |
|---|
| 831 | | - rk_pcie_debug_dump(rk_pcie); |
|---|
| 774 | + /* |
|---|
| 775 | + * In resume routine, function devices' resume function must be late after |
|---|
| 776 | + * controllers'. Some devices, such as Wi-Fi, need special IO setting before |
|---|
| 777 | + * finishing training. So there must be timeout here. These kinds of devices |
|---|
| 778 | + * need rescan devices by its driver when used. So no need to waste time waiting |
|---|
| 779 | + * for training pass. |
|---|
| 780 | + */ |
|---|
| 781 | + if (rk_pcie->in_suspend && rk_pcie->skip_scan_in_resume) { |
|---|
| 782 | + rfkill_get_wifi_power_state(&power); |
|---|
| 783 | + if (!power) { |
|---|
| 784 | + gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1); |
|---|
| 832 | 785 | return 0; |
|---|
| 833 | 786 | } |
|---|
| 834 | 787 | } |
|---|
| 835 | 788 | |
|---|
| 836 | | - dev_info_ratelimited(pci->dev, "PCIe Linking... LTSSM is 0x%x\n", |
|---|
| 837 | | - rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS)); |
|---|
| 838 | | - rk_pcie_debug_dump(rk_pcie); |
|---|
| 839 | | - msleep(20); |
|---|
| 840 | | - } |
|---|
| 789 | + /* |
|---|
| 790 | + * PCIe requires the refclk to be stable for 100µs prior to releasing |
|---|
| 791 | + * PERST and T_PVPERL (Power stable to PERST# inactive) should be a |
|---|
| 792 | + * minimum of 100ms. See table 2-4 in section 2.6.2 AC, the PCI Express |
|---|
| 793 | + * Card Electromechanical Specification 3.0. So 100ms in total is the min |
|---|
| 794 | + * requuirement here. We add a 200ms by default for sake of hoping everthings |
|---|
| 795 | + * work fine. If it doesn't, please add more in DT node by add rockchip,perst-inactive-ms. |
|---|
| 796 | + */ |
|---|
| 797 | + msleep(rk_pcie->perst_inactive_ms); |
|---|
| 798 | + gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1); |
|---|
| 841 | 799 | |
|---|
| 842 | | - dev_err(pci->dev, "PCIe Link Fail\n"); |
|---|
| 800 | + /* |
|---|
| 801 | + * Add this 1ms delay because we observe link is always up stably after it and |
|---|
| 802 | + * could help us save 20ms for scanning devices. |
|---|
| 803 | + */ |
|---|
| 804 | + usleep_range(1000, 1100); |
|---|
| 805 | + |
|---|
| 806 | + for (retries = 0; retries < 100; retries++) { |
|---|
| 807 | + if (dw_pcie_link_up(pci)) { |
|---|
| 808 | + /* |
|---|
| 809 | + * We may be here in case of L0 in Gen1. But if EP is capable |
|---|
| 810 | + * of Gen2 or Gen3, Gen switch may happen just in this time, but |
|---|
| 811 | + * we keep on accessing devices in unstable link status. Given |
|---|
| 812 | + * that LTSSM max timeout is 24ms per period, we can wait a bit |
|---|
| 813 | + * more for Gen switch. |
|---|
| 814 | + */ |
|---|
| 815 | + msleep(50); |
|---|
| 816 | + /* In case link drop after linkup, double check it */ |
|---|
| 817 | + if (dw_pcie_link_up(pci)) { |
|---|
| 818 | + dev_info(pci->dev, "PCIe Link up, LTSSM is 0x%x\n", |
|---|
| 819 | + rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS)); |
|---|
| 820 | + rk_pcie_debug_dump(rk_pcie); |
|---|
| 821 | + return 0; |
|---|
| 822 | + } |
|---|
| 823 | + } |
|---|
| 824 | + |
|---|
| 825 | + dev_info_ratelimited(pci->dev, "PCIe Linking... LTSSM is 0x%x\n", |
|---|
| 826 | + rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS)); |
|---|
| 827 | + rk_pcie_debug_dump(rk_pcie); |
|---|
| 828 | + msleep(20); |
|---|
| 829 | + } |
|---|
| 830 | + |
|---|
| 831 | + /* |
|---|
| 832 | + * In response to the situation where PCIe peripherals cannot be |
|---|
| 833 | + * enumerated due tosignal abnormalities, reset PERST# and reset |
|---|
| 834 | + * the peripheral power supply, then restart the enumeration. |
|---|
| 835 | + */ |
|---|
| 836 | + ltssm = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS); |
|---|
| 837 | + dev_err(pci->dev, "PCIe Link Fail, LTSSM is 0x%x, hw_retries=%d\n", ltssm, hw_retries); |
|---|
| 838 | + if (ltssm >= 3 && !rk_pcie->is_signal_test) { |
|---|
| 839 | + rk_pcie_disable_power(rk_pcie); |
|---|
| 840 | + msleep(1000); |
|---|
| 841 | + rk_pcie_enable_power(rk_pcie); |
|---|
| 842 | + } else { |
|---|
| 843 | + break; |
|---|
| 844 | + } |
|---|
| 845 | + } |
|---|
| 843 | 846 | |
|---|
| 844 | 847 | return rk_pcie->is_signal_test == true ? 0 : -EINVAL; |
|---|
| 845 | 848 | } |
|---|
| .. | .. |
|---|
| 1129 | 1132 | dw_pcie_setup_rc(pp); |
|---|
| 1130 | 1133 | |
|---|
| 1131 | 1134 | /* Disable BAR0 BAR1 */ |
|---|
| 1132 | | - dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + BAR_0 * 4, 0); |
|---|
| 1133 | | - dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + BAR_1 * 4, 0); |
|---|
| 1135 | + dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, 0x0); |
|---|
| 1136 | + dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_1, 0x0); |
|---|
| 1134 | 1137 | |
|---|
| 1135 | 1138 | ret = rk_pcie_establish_link(pci); |
|---|
| 1136 | 1139 | |
|---|
| .. | .. |
|---|
| 1203 | 1206 | return ret; |
|---|
| 1204 | 1207 | } |
|---|
| 1205 | 1208 | |
|---|
| 1206 | | - rk_pcie->pci->dbi_base2 = rk_pcie->pci->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET; |
|---|
| 1207 | 1209 | rk_pcie->pci->atu_base = rk_pcie->pci->dbi_base + DEFAULT_DBI_ATU_OFFSET; |
|---|
| 1208 | 1210 | rk_pcie->pci->iatu_unroll_enabled = rk_pcie_iatu_unroll_enabled(rk_pcie->pci); |
|---|
| 1209 | 1211 | |
|---|
| .. | .. |
|---|
| 1263 | 1265 | return PTR_ERR(rk_pcie->dbi_base); |
|---|
| 1264 | 1266 | |
|---|
| 1265 | 1267 | rk_pcie->pci->dbi_base = rk_pcie->dbi_base; |
|---|
| 1268 | + rk_pcie->pci->dbi_base2 = rk_pcie->pci->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET; |
|---|
| 1266 | 1269 | |
|---|
| 1267 | 1270 | apb_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
|---|
| 1268 | 1271 | "pcie-apb"); |
|---|
| .. | .. |
|---|
| 1601 | 1604 | |
|---|
| 1602 | 1605 | static const struct dw_pcie_ops dw_pcie_ops = { |
|---|
| 1603 | 1606 | .start_link = rk_pcie_establish_link, |
|---|
| 1604 | | - .link_up = rk_pcie_link_up, |
|---|
| 1605 | 1607 | }; |
|---|
| 1606 | 1608 | |
|---|
| 1607 | 1609 | static int rk1808_pcie_fixup(struct rk_pcie *rk_pcie, struct device_node *np) |
|---|
| .. | .. |
|---|
| 1988 | 1990 | |
|---|
| 1989 | 1991 | if (!IS_ERR_OR_NULL(rk_pcie->prsnt_gpio)) { |
|---|
| 1990 | 1992 | if (!gpiod_get_value(rk_pcie->prsnt_gpio)) { |
|---|
| 1993 | + dev_info(dev, "device isn't present\n"); |
|---|
| 1991 | 1994 | ret = -ENODEV; |
|---|
| 1992 | 1995 | goto release_driver; |
|---|
| 1993 | 1996 | } |
|---|
| .. | .. |
|---|
| 2354 | 2357 | no_l2: |
|---|
| 2355 | 2358 | rk_pcie_disable_ltssm(rk_pcie); |
|---|
| 2356 | 2359 | |
|---|
| 2360 | + ret = phy_validate(rk_pcie->phy, PHY_TYPE_PCIE, 0, NULL); |
|---|
| 2361 | + if (ret && ret != -EOPNOTSUPP) { |
|---|
| 2362 | + dev_err(dev, "PHY is reused by other controller, check the dts!\n"); |
|---|
| 2363 | + return ret; |
|---|
| 2364 | + } |
|---|
| 2365 | + |
|---|
| 2357 | 2366 | /* make sure assert phy success */ |
|---|
| 2358 | 2367 | usleep_range(200, 300); |
|---|
| 2359 | 2368 | |
|---|