|
6 | 6 | * Author: Jianjun Wang <[email protected]>
|
7 | 7 | */
|
8 | 8 |
|
| 9 | +#include <linux/bitfield.h> |
9 | 10 | #include <linux/clk.h>
|
| 11 | +#include <linux/clk-provider.h> |
10 | 12 | #include <linux/delay.h>
|
11 | 13 | #include <linux/iopoll.h>
|
12 | 14 | #include <linux/irq.h>
|
|
15 | 17 | #include <linux/kernel.h>
|
16 | 18 | #include <linux/module.h>
|
17 | 19 | #include <linux/msi.h>
|
| 20 | +#include <linux/of_device.h> |
| 21 | +#include <linux/of_pci.h> |
18 | 22 | #include <linux/pci.h>
|
19 | 23 | #include <linux/phy/phy.h>
|
20 | 24 | #include <linux/platform_device.h>
|
|
29 | 33 | #define PCI_CLASS(class) (class << 8)
|
30 | 34 | #define PCIE_RC_MODE BIT(0)
|
31 | 35 |
|
| 36 | +#define PCIE_EQ_PRESET_01_REG 0x100 |
| 37 | +#define PCIE_VAL_LN0_DOWNSTREAM GENMASK(6, 0) |
| 38 | +#define PCIE_VAL_LN0_UPSTREAM GENMASK(14, 8) |
| 39 | +#define PCIE_VAL_LN1_DOWNSTREAM GENMASK(22, 16) |
| 40 | +#define PCIE_VAL_LN1_UPSTREAM GENMASK(30, 24) |
| 41 | + |
32 | 42 | #define PCIE_CFGNUM_REG 0x140
|
33 | 43 | #define PCIE_CFG_DEVFN(devfn) ((devfn) & GENMASK(7, 0))
|
34 | 44 | #define PCIE_CFG_BUS(bus) (((bus) << 8) & GENMASK(15, 8))
|
|
68 | 78 | #define PCIE_MSI_SET_ENABLE_REG 0x190
|
69 | 79 | #define PCIE_MSI_SET_ENABLE GENMASK(PCIE_MSI_SET_NUM - 1, 0)
|
70 | 80 |
|
| 81 | +#define PCIE_PIPE4_PIE8_REG 0x338 |
| 82 | +#define PCIE_K_FINETUNE_MAX GENMASK(5, 0) |
| 83 | +#define PCIE_K_FINETUNE_ERR GENMASK(7, 6) |
| 84 | +#define PCIE_K_PRESET_TO_USE GENMASK(18, 8) |
| 85 | +#define PCIE_K_PHYPARAM_QUERY BIT(19) |
| 86 | +#define PCIE_K_QUERY_TIMEOUT BIT(20) |
| 87 | +#define PCIE_K_PRESET_TO_USE_16G GENMASK(31, 21) |
| 88 | + |
71 | 89 | #define PCIE_MSI_SET_BASE_REG 0xc00
|
72 | 90 | #define PCIE_MSI_SET_OFFSET 0x10
|
73 | 91 | #define PCIE_MSI_SET_STATUS_OFFSET 0x04
|
|
100 | 118 | #define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
101 | 119 | #define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
102 | 120 |
|
103 |
| -#define MAX_NUM_PHY_RESETS 1 |
| 121 | +#define MAX_NUM_PHY_RESETS 3 |
| 122 | + |
| 123 | +/* Time in ms needed to complete PCIe reset on EN7581 SoC */ |
| 124 | +#define PCIE_EN7581_RESET_TIME_MS 100 |
104 | 125 |
|
105 | 126 | struct mtk_gen3_pcie;
|
106 | 127 |
|
@@ -847,6 +868,85 @@ static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
|
847 | 868 | return 0;
|
848 | 869 | }
|
849 | 870 |
|
| 871 | +static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie) |
| 872 | +{ |
| 873 | + struct device *dev = pcie->dev; |
| 874 | + int err; |
| 875 | + u32 val; |
| 876 | + |
| 877 | + /* |
| 878 | + * Wait for the time needed to complete the bulk assert in |
| 879 | + * mtk_pcie_setup for EN7581 SoC. |
| 880 | + */ |
| 881 | + mdelay(PCIE_EN7581_RESET_TIME_MS); |
| 882 | + |
| 883 | + err = phy_init(pcie->phy); |
| 884 | + if (err) { |
| 885 | + dev_err(dev, "failed to initialize PHY\n"); |
| 886 | + return err; |
| 887 | + } |
| 888 | + |
| 889 | + err = phy_power_on(pcie->phy); |
| 890 | + if (err) { |
| 891 | + dev_err(dev, "failed to power on PHY\n"); |
| 892 | + goto err_phy_on; |
| 893 | + } |
| 894 | + |
| 895 | + err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets); |
| 896 | + if (err) { |
| 897 | + dev_err(dev, "failed to deassert PHYs\n"); |
| 898 | + goto err_phy_deassert; |
| 899 | + } |
| 900 | + |
| 901 | + /* |
| 902 | + * Wait for the time needed to complete the bulk de-assert above. |
| 903 | + * This time is specific for EN7581 SoC. |
| 904 | + */ |
| 905 | + mdelay(PCIE_EN7581_RESET_TIME_MS); |
| 906 | + |
| 907 | + pm_runtime_enable(dev); |
| 908 | + pm_runtime_get_sync(dev); |
| 909 | + |
| 910 | + err = clk_bulk_prepare(pcie->num_clks, pcie->clks); |
| 911 | + if (err) { |
| 912 | + dev_err(dev, "failed to prepare clock\n"); |
| 913 | + goto err_clk_prepare; |
| 914 | + } |
| 915 | + |
| 916 | + val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) | |
| 917 | + FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) | |
| 918 | + FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) | |
| 919 | + FIELD_PREP(PCIE_VAL_LN1_UPSTREAM, 0x41); |
| 920 | + writel_relaxed(val, pcie->base + PCIE_EQ_PRESET_01_REG); |
| 921 | + |
| 922 | + val = PCIE_K_PHYPARAM_QUERY | PCIE_K_QUERY_TIMEOUT | |
| 923 | + FIELD_PREP(PCIE_K_PRESET_TO_USE_16G, 0x80) | |
| 924 | + FIELD_PREP(PCIE_K_PRESET_TO_USE, 0x2) | |
| 925 | + FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf); |
| 926 | + writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG); |
| 927 | + |
| 928 | + err = clk_bulk_enable(pcie->num_clks, pcie->clks); |
| 929 | + if (err) { |
| 930 | + dev_err(dev, "failed to prepare clock\n"); |
| 931 | + goto err_clk_enable; |
| 932 | + } |
| 933 | + |
| 934 | + return 0; |
| 935 | + |
| 936 | +err_clk_enable: |
| 937 | + clk_bulk_unprepare(pcie->num_clks, pcie->clks); |
| 938 | +err_clk_prepare: |
| 939 | + pm_runtime_put_sync(dev); |
| 940 | + pm_runtime_disable(dev); |
| 941 | + reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets); |
| 942 | +err_phy_deassert: |
| 943 | + phy_power_off(pcie->phy); |
| 944 | +err_phy_on: |
| 945 | + phy_exit(pcie->phy); |
| 946 | + |
| 947 | + return err; |
| 948 | +} |
| 949 | + |
850 | 950 | static int mtk_pcie_power_up(struct mtk_gen3_pcie *pcie)
|
851 | 951 | {
|
852 | 952 | struct device *dev = pcie->dev;
|
@@ -1113,7 +1213,18 @@ static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_mt8192 = {
|
1113 | 1213 | },
|
1114 | 1214 | };
|
1115 | 1215 |
|
| 1216 | +static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_en7581 = { |
| 1217 | + .power_up = mtk_pcie_en7581_power_up, |
| 1218 | + .phy_resets = { |
| 1219 | + .id[0] = "phy-lane0", |
| 1220 | + .id[1] = "phy-lane1", |
| 1221 | + .id[2] = "phy-lane2", |
| 1222 | + .num_resets = 3, |
| 1223 | + }, |
| 1224 | +}; |
| 1225 | + |
1116 | 1226 | static const struct of_device_id mtk_pcie_of_match[] = {
|
| 1227 | + { .compatible = "airoha,en7581-pcie", .data = &mtk_pcie_soc_en7581 }, |
1117 | 1228 | { .compatible = "mediatek,mt8192-pcie", .data = &mtk_pcie_soc_mt8192 },
|
1118 | 1229 | {},
|
1119 | 1230 | };
|
|
0 commit comments