diff options
-rw-r--r-- | Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt | 29 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/samsung-phy.txt | 17 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-exynos.c | 559 | ||||
-rw-r--r-- | drivers/phy/Kconfig | 8 | ||||
-rw-r--r-- | drivers/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/phy/phy-exynos-pcie.c | 285 |
6 files changed, 673 insertions, 226 deletions
diff --git a/Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt b/Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt index 4f9d23d2ed67..7d3b09474657 100644 --- a/Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt +++ b/Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt | |||
@@ -7,8 +7,19 @@ Required properties: | |||
7 | - compatible: "samsung,exynos5440-pcie" | 7 | - compatible: "samsung,exynos5440-pcie" |
8 | - reg: base addresses and lengths of the pcie controller, | 8 | - reg: base addresses and lengths of the pcie controller, |
9 | the phy controller, additional register for the phy controller. | 9 | the phy controller, additional register for the phy controller. |
10 | (Registers for the phy controller are DEPRECATED. | ||
11 | Use the PHY framework.) | ||
12 | - reg-names : First name should be set to "elbi". | ||
13 | And use the "config" instead of getting the confgiruation address space | ||
14 | from "ranges". | ||
15 | NOTE: When use the "config" property, reg-names must be set. | ||
10 | - interrupts: A list of interrupt outputs for level interrupt, | 16 | - interrupts: A list of interrupt outputs for level interrupt, |
11 | pulse interrupt, special interrupt. | 17 | pulse interrupt, special interrupt. |
18 | - phys: From PHY binding. Phandle for the Generic PHY. | ||
19 | Refer to Documentation/devicetree/bindings/phy/samsung-phy.txt | ||
20 | |||
21 | Other common properties refer to | ||
22 | Documentation/devicetree/binding/pci/designware-pcie.txt | ||
12 | 23 | ||
13 | Example: | 24 | Example: |
14 | 25 | ||
@@ -54,6 +65,24 @@ SoC specific DT Entry: | |||
54 | num-lanes = <4>; | 65 | num-lanes = <4>; |
55 | }; | 66 | }; |
56 | 67 | ||
68 | With using PHY framework: | ||
69 | pcie_phy0: pcie-phy@270000 { | ||
70 | ... | ||
71 | reg = <0x270000 0x1000>, <0x271000 0x40>; | ||
72 | reg-names = "phy", "block"; | ||
73 | ... | ||
74 | }; | ||
75 | |||
76 | pcie@290000 { | ||
77 | ... | ||
78 | reg = <0x290000 0x1000>, <0x40000000 0x1000>; | ||
79 | reg-names = "elbi", "config"; | ||
80 | phys = <&pcie_phy0>; | ||
81 | ranges = <0x81000000 0 0 0x60001000 0 0x00010000 | ||
82 | 0x82000000 0 0x60011000 0x60011000 0 0x1ffef000>; | ||
83 | ... | ||
84 | }; | ||
85 | |||
57 | Board specific DT Entry: | 86 | Board specific DT Entry: |
58 | 87 | ||
59 | pcie@290000 { | 88 | pcie@290000 { |
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt index 9872ba8546bd..ab80bfe31cb3 100644 --- a/Documentation/devicetree/bindings/phy/samsung-phy.txt +++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt | |||
@@ -191,3 +191,20 @@ Example: | |||
191 | usbdrdphy0 = &usb3_phy0; | 191 | usbdrdphy0 = &usb3_phy0; |
192 | usbdrdphy1 = &usb3_phy1; | 192 | usbdrdphy1 = &usb3_phy1; |
193 | }; | 193 | }; |
194 | |||
195 | Samsung Exynos SoC series PCIe PHY controller | ||
196 | -------------------------------------------------- | ||
197 | Required properties: | ||
198 | - compatible : Should be set to "samsung,exynos5440-pcie-phy" | ||
199 | - #phy-cells : Must be zero | ||
200 | - reg : a register used by phy driver. | ||
201 | - First is for phy register, second is for block register. | ||
202 | - reg-names : Must be set to "phy" and "block". | ||
203 | |||
204 | Example: | ||
205 | pcie_phy0: pcie-phy@270000 { | ||
206 | #phy-cells = <0>; | ||
207 | compatible = "samsung,exynos5440-pcie-phy"; | ||
208 | reg = <0x270000 0x1000>, <0x271000 0x40>; | ||
209 | reg-names = "phy", "block"; | ||
210 | }; | ||
diff --git a/drivers/pci/dwc/pci-exynos.c b/drivers/pci/dwc/pci-exynos.c index 0295ec96f3d0..001c91a945aa 100644 --- a/drivers/pci/dwc/pci-exynos.c +++ b/drivers/pci/dwc/pci-exynos.c | |||
@@ -17,9 +17,11 @@ | |||
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/of_device.h> | ||
20 | #include <linux/of_gpio.h> | 21 | #include <linux/of_gpio.h> |
21 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
22 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/phy/phy.h> | ||
23 | #include <linux/resource.h> | 25 | #include <linux/resource.h> |
24 | #include <linux/signal.h> | 26 | #include <linux/signal.h> |
25 | #include <linux/types.h> | 27 | #include <linux/types.h> |
@@ -28,31 +30,21 @@ | |||
28 | 30 | ||
29 | #define to_exynos_pcie(x) dev_get_drvdata((x)->dev) | 31 | #define to_exynos_pcie(x) dev_get_drvdata((x)->dev) |
30 | 32 | ||
31 | struct exynos_pcie { | ||
32 | struct dw_pcie *pci; | ||
33 | void __iomem *elbi_base; /* DT 0th resource */ | ||
34 | void __iomem *phy_base; /* DT 1st resource */ | ||
35 | void __iomem *block_base; /* DT 2nd resource */ | ||
36 | int reset_gpio; | ||
37 | struct clk *clk; | ||
38 | struct clk *bus_clk; | ||
39 | }; | ||
40 | |||
41 | /* PCIe ELBI registers */ | 33 | /* PCIe ELBI registers */ |
42 | #define PCIE_IRQ_PULSE 0x000 | 34 | #define PCIE_IRQ_PULSE 0x000 |
43 | #define IRQ_INTA_ASSERT (0x1 << 0) | 35 | #define IRQ_INTA_ASSERT BIT(0) |
44 | #define IRQ_INTB_ASSERT (0x1 << 2) | 36 | #define IRQ_INTB_ASSERT BIT(2) |
45 | #define IRQ_INTC_ASSERT (0x1 << 4) | 37 | #define IRQ_INTC_ASSERT BIT(4) |
46 | #define IRQ_INTD_ASSERT (0x1 << 6) | 38 | #define IRQ_INTD_ASSERT BIT(6) |
47 | #define PCIE_IRQ_LEVEL 0x004 | 39 | #define PCIE_IRQ_LEVEL 0x004 |
48 | #define PCIE_IRQ_SPECIAL 0x008 | 40 | #define PCIE_IRQ_SPECIAL 0x008 |
49 | #define PCIE_IRQ_EN_PULSE 0x00c | 41 | #define PCIE_IRQ_EN_PULSE 0x00c |
50 | #define PCIE_IRQ_EN_LEVEL 0x010 | 42 | #define PCIE_IRQ_EN_LEVEL 0x010 |
51 | #define IRQ_MSI_ENABLE (0x1 << 2) | 43 | #define IRQ_MSI_ENABLE BIT(2) |
52 | #define PCIE_IRQ_EN_SPECIAL 0x014 | 44 | #define PCIE_IRQ_EN_SPECIAL 0x014 |
53 | #define PCIE_PWR_RESET 0x018 | 45 | #define PCIE_PWR_RESET 0x018 |
54 | #define PCIE_CORE_RESET 0x01c | 46 | #define PCIE_CORE_RESET 0x01c |
55 | #define PCIE_CORE_RESET_ENABLE (0x1 << 0) | 47 | #define PCIE_CORE_RESET_ENABLE BIT(0) |
56 | #define PCIE_STICKY_RESET 0x020 | 48 | #define PCIE_STICKY_RESET 0x020 |
57 | #define PCIE_NONSTICKY_RESET 0x024 | 49 | #define PCIE_NONSTICKY_RESET 0x024 |
58 | #define PCIE_APP_INIT_RESET 0x028 | 50 | #define PCIE_APP_INIT_RESET 0x028 |
@@ -61,7 +53,7 @@ struct exynos_pcie { | |||
61 | #define PCIE_ELBI_LTSSM_ENABLE 0x1 | 53 | #define PCIE_ELBI_LTSSM_ENABLE 0x1 |
62 | #define PCIE_ELBI_SLV_AWMISC 0x11c | 54 | #define PCIE_ELBI_SLV_AWMISC 0x11c |
63 | #define PCIE_ELBI_SLV_ARMISC 0x120 | 55 | #define PCIE_ELBI_SLV_ARMISC 0x120 |
64 | #define PCIE_ELBI_SLV_DBI_ENABLE (0x1 << 21) | 56 | #define PCIE_ELBI_SLV_DBI_ENABLE BIT(21) |
65 | 57 | ||
66 | /* PCIe Purple registers */ | 58 | /* PCIe Purple registers */ |
67 | #define PCIE_PHY_GLOBAL_RESET 0x000 | 59 | #define PCIE_PHY_GLOBAL_RESET 0x000 |
@@ -79,235 +71,334 @@ struct exynos_pcie { | |||
79 | #define PCIE_PHY_DCC_FEEDBACK 0x014 | 71 | #define PCIE_PHY_DCC_FEEDBACK 0x014 |
80 | #define PCIE_PHY_PLL_DIV_1 0x05c | 72 | #define PCIE_PHY_PLL_DIV_1 0x05c |
81 | #define PCIE_PHY_COMMON_POWER 0x064 | 73 | #define PCIE_PHY_COMMON_POWER 0x064 |
82 | #define PCIE_PHY_COMMON_PD_CMN (0x1 << 3) | 74 | #define PCIE_PHY_COMMON_PD_CMN BIT(3) |
83 | #define PCIE_PHY_TRSV0_EMP_LVL 0x084 | 75 | #define PCIE_PHY_TRSV0_EMP_LVL 0x084 |
84 | #define PCIE_PHY_TRSV0_DRV_LVL 0x088 | 76 | #define PCIE_PHY_TRSV0_DRV_LVL 0x088 |
85 | #define PCIE_PHY_TRSV0_RXCDR 0x0ac | 77 | #define PCIE_PHY_TRSV0_RXCDR 0x0ac |
86 | #define PCIE_PHY_TRSV0_POWER 0x0c4 | 78 | #define PCIE_PHY_TRSV0_POWER 0x0c4 |
87 | #define PCIE_PHY_TRSV0_PD_TSV (0x1 << 7) | 79 | #define PCIE_PHY_TRSV0_PD_TSV BIT(7) |
88 | #define PCIE_PHY_TRSV0_LVCC 0x0dc | 80 | #define PCIE_PHY_TRSV0_LVCC 0x0dc |
89 | #define PCIE_PHY_TRSV1_EMP_LVL 0x144 | 81 | #define PCIE_PHY_TRSV1_EMP_LVL 0x144 |
90 | #define PCIE_PHY_TRSV1_RXCDR 0x16c | 82 | #define PCIE_PHY_TRSV1_RXCDR 0x16c |
91 | #define PCIE_PHY_TRSV1_POWER 0x184 | 83 | #define PCIE_PHY_TRSV1_POWER 0x184 |
92 | #define PCIE_PHY_TRSV1_PD_TSV (0x1 << 7) | 84 | #define PCIE_PHY_TRSV1_PD_TSV BIT(7) |
93 | #define PCIE_PHY_TRSV1_LVCC 0x19c | 85 | #define PCIE_PHY_TRSV1_LVCC 0x19c |
94 | #define PCIE_PHY_TRSV2_EMP_LVL 0x204 | 86 | #define PCIE_PHY_TRSV2_EMP_LVL 0x204 |
95 | #define PCIE_PHY_TRSV2_RXCDR 0x22c | 87 | #define PCIE_PHY_TRSV2_RXCDR 0x22c |
96 | #define PCIE_PHY_TRSV2_POWER 0x244 | 88 | #define PCIE_PHY_TRSV2_POWER 0x244 |
97 | #define PCIE_PHY_TRSV2_PD_TSV (0x1 << 7) | 89 | #define PCIE_PHY_TRSV2_PD_TSV BIT(7) |
98 | #define PCIE_PHY_TRSV2_LVCC 0x25c | 90 | #define PCIE_PHY_TRSV2_LVCC 0x25c |
99 | #define PCIE_PHY_TRSV3_EMP_LVL 0x2c4 | 91 | #define PCIE_PHY_TRSV3_EMP_LVL 0x2c4 |
100 | #define PCIE_PHY_TRSV3_RXCDR 0x2ec | 92 | #define PCIE_PHY_TRSV3_RXCDR 0x2ec |
101 | #define PCIE_PHY_TRSV3_POWER 0x304 | 93 | #define PCIE_PHY_TRSV3_POWER 0x304 |
102 | #define PCIE_PHY_TRSV3_PD_TSV (0x1 << 7) | 94 | #define PCIE_PHY_TRSV3_PD_TSV BIT(7) |
103 | #define PCIE_PHY_TRSV3_LVCC 0x31c | 95 | #define PCIE_PHY_TRSV3_LVCC 0x31c |
104 | 96 | ||
105 | static void exynos_elb_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg) | 97 | struct exynos_pcie_mem_res { |
98 | void __iomem *elbi_base; /* DT 0th resource: PCIe CTRL */ | ||
99 | void __iomem *phy_base; /* DT 1st resource: PHY CTRL */ | ||
100 | void __iomem *block_base; /* DT 2nd resource: PHY ADDITIONAL CTRL */ | ||
101 | }; | ||
102 | |||
103 | struct exynos_pcie_clk_res { | ||
104 | struct clk *clk; | ||
105 | struct clk *bus_clk; | ||
106 | }; | ||
107 | |||
108 | struct exynos_pcie { | ||
109 | struct dw_pcie *pci; | ||
110 | struct exynos_pcie_mem_res *mem_res; | ||
111 | struct exynos_pcie_clk_res *clk_res; | ||
112 | const struct exynos_pcie_ops *ops; | ||
113 | int reset_gpio; | ||
114 | |||
115 | /* For Generic PHY Framework */ | ||
116 | bool using_phy; | ||
117 | struct phy *phy; | ||
118 | }; | ||
119 | |||
120 | struct exynos_pcie_ops { | ||
121 | int (*get_mem_resources)(struct platform_device *pdev, | ||
122 | struct exynos_pcie *ep); | ||
123 | int (*get_clk_resources)(struct exynos_pcie *ep); | ||
124 | int (*init_clk_resources)(struct exynos_pcie *ep); | ||
125 | void (*deinit_clk_resources)(struct exynos_pcie *ep); | ||
126 | }; | ||
127 | |||
128 | static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev, | ||
129 | struct exynos_pcie *ep) | ||
106 | { | 130 | { |
107 | writel(val, exynos_pcie->elbi_base + reg); | 131 | struct dw_pcie *pci = ep->pci; |
132 | struct device *dev = pci->dev; | ||
133 | struct resource *res; | ||
134 | |||
135 | /* If using the PHY framework, doesn't need to get other resource */ | ||
136 | if (ep->using_phy) | ||
137 | return 0; | ||
138 | |||
139 | ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL); | ||
140 | if (!ep->mem_res) | ||
141 | return -ENOMEM; | ||
142 | |||
143 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
144 | ep->mem_res->elbi_base = devm_ioremap_resource(dev, res); | ||
145 | if (IS_ERR(ep->mem_res->elbi_base)) | ||
146 | return PTR_ERR(ep->mem_res->elbi_base); | ||
147 | |||
148 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
149 | ep->mem_res->phy_base = devm_ioremap_resource(dev, res); | ||
150 | if (IS_ERR(ep->mem_res->phy_base)) | ||
151 | return PTR_ERR(ep->mem_res->phy_base); | ||
152 | |||
153 | res = platform_get_resource(pdev, IORESOURCE_MEM, 2); | ||
154 | ep->mem_res->block_base = devm_ioremap_resource(dev, res); | ||
155 | if (IS_ERR(ep->mem_res->block_base)) | ||
156 | return PTR_ERR(ep->mem_res->block_base); | ||
157 | |||
158 | return 0; | ||
108 | } | 159 | } |
109 | 160 | ||
110 | static u32 exynos_elb_readl(struct exynos_pcie *exynos_pcie, u32 reg) | 161 | static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep) |
111 | { | 162 | { |
112 | return readl(exynos_pcie->elbi_base + reg); | 163 | struct dw_pcie *pci = ep->pci; |
164 | struct device *dev = pci->dev; | ||
165 | |||
166 | ep->clk_res = devm_kzalloc(dev, sizeof(*ep->clk_res), GFP_KERNEL); | ||
167 | if (!ep->clk_res) | ||
168 | return -ENOMEM; | ||
169 | |||
170 | ep->clk_res->clk = devm_clk_get(dev, "pcie"); | ||
171 | if (IS_ERR(ep->clk_res->clk)) { | ||
172 | dev_err(dev, "Failed to get pcie rc clock\n"); | ||
173 | return PTR_ERR(ep->clk_res->clk); | ||
174 | } | ||
175 | |||
176 | ep->clk_res->bus_clk = devm_clk_get(dev, "pcie_bus"); | ||
177 | if (IS_ERR(ep->clk_res->bus_clk)) { | ||
178 | dev_err(dev, "Failed to get pcie bus clock\n"); | ||
179 | return PTR_ERR(ep->clk_res->bus_clk); | ||
180 | } | ||
181 | |||
182 | return 0; | ||
113 | } | 183 | } |
114 | 184 | ||
115 | static void exynos_phy_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg) | 185 | static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep) |
116 | { | 186 | { |
117 | writel(val, exynos_pcie->phy_base + reg); | 187 | struct dw_pcie *pci = ep->pci; |
188 | struct device *dev = pci->dev; | ||
189 | int ret; | ||
190 | |||
191 | ret = clk_prepare_enable(ep->clk_res->clk); | ||
192 | if (ret) { | ||
193 | dev_err(dev, "cannot enable pcie rc clock"); | ||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | ret = clk_prepare_enable(ep->clk_res->bus_clk); | ||
198 | if (ret) { | ||
199 | dev_err(dev, "cannot enable pcie bus clock"); | ||
200 | goto err_bus_clk; | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | |||
205 | err_bus_clk: | ||
206 | clk_disable_unprepare(ep->clk_res->clk); | ||
207 | |||
208 | return ret; | ||
118 | } | 209 | } |
119 | 210 | ||
120 | static u32 exynos_phy_readl(struct exynos_pcie *exynos_pcie, u32 reg) | 211 | static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep) |
121 | { | 212 | { |
122 | return readl(exynos_pcie->phy_base + reg); | 213 | clk_disable_unprepare(ep->clk_res->bus_clk); |
214 | clk_disable_unprepare(ep->clk_res->clk); | ||
123 | } | 215 | } |
124 | 216 | ||
125 | static void exynos_blk_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg) | 217 | static const struct exynos_pcie_ops exynos5440_pcie_ops = { |
218 | .get_mem_resources = exynos5440_pcie_get_mem_resources, | ||
219 | .get_clk_resources = exynos5440_pcie_get_clk_resources, | ||
220 | .init_clk_resources = exynos5440_pcie_init_clk_resources, | ||
221 | .deinit_clk_resources = exynos5440_pcie_deinit_clk_resources, | ||
222 | }; | ||
223 | |||
224 | static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg) | ||
126 | { | 225 | { |
127 | writel(val, exynos_pcie->block_base + reg); | 226 | writel(val, base + reg); |
128 | } | 227 | } |
129 | 228 | ||
130 | static u32 exynos_blk_readl(struct exynos_pcie *exynos_pcie, u32 reg) | 229 | static u32 exynos_pcie_readl(void __iomem *base, u32 reg) |
131 | { | 230 | { |
132 | return readl(exynos_pcie->block_base + reg); | 231 | return readl(base + reg); |
133 | } | 232 | } |
134 | 233 | ||
135 | static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *exynos_pcie, | 234 | static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on) |
136 | bool on) | ||
137 | { | 235 | { |
138 | u32 val; | 236 | u32 val; |
139 | 237 | ||
140 | if (on) { | 238 | val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_AWMISC); |
141 | val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_AWMISC); | 239 | if (on) |
142 | val |= PCIE_ELBI_SLV_DBI_ENABLE; | 240 | val |= PCIE_ELBI_SLV_DBI_ENABLE; |
143 | exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_AWMISC); | 241 | else |
144 | } else { | ||
145 | val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_AWMISC); | ||
146 | val &= ~PCIE_ELBI_SLV_DBI_ENABLE; | 242 | val &= ~PCIE_ELBI_SLV_DBI_ENABLE; |
147 | exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_AWMISC); | 243 | exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_AWMISC); |
148 | } | ||
149 | } | 244 | } |
150 | 245 | ||
151 | static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *exynos_pcie, | 246 | static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on) |
152 | bool on) | ||
153 | { | 247 | { |
154 | u32 val; | 248 | u32 val; |
155 | 249 | ||
156 | if (on) { | 250 | val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_ARMISC); |
157 | val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_ARMISC); | 251 | if (on) |
158 | val |= PCIE_ELBI_SLV_DBI_ENABLE; | 252 | val |= PCIE_ELBI_SLV_DBI_ENABLE; |
159 | exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_ARMISC); | 253 | else |
160 | } else { | ||
161 | val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_ARMISC); | ||
162 | val &= ~PCIE_ELBI_SLV_DBI_ENABLE; | 254 | val &= ~PCIE_ELBI_SLV_DBI_ENABLE; |
163 | exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_ARMISC); | 255 | exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_ARMISC); |
164 | } | ||
165 | } | 256 | } |
166 | 257 | ||
167 | static void exynos_pcie_assert_core_reset(struct exynos_pcie *exynos_pcie) | 258 | static void exynos_pcie_assert_core_reset(struct exynos_pcie *ep) |
168 | { | 259 | { |
169 | u32 val; | 260 | u32 val; |
170 | 261 | ||
171 | val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET); | 262 | val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); |
172 | val &= ~PCIE_CORE_RESET_ENABLE; | 263 | val &= ~PCIE_CORE_RESET_ENABLE; |
173 | exynos_elb_writel(exynos_pcie, val, PCIE_CORE_RESET); | 264 | exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET); |
174 | exynos_elb_writel(exynos_pcie, 0, PCIE_PWR_RESET); | 265 | exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_PWR_RESET); |
175 | exynos_elb_writel(exynos_pcie, 0, PCIE_STICKY_RESET); | 266 | exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_STICKY_RESET); |
176 | exynos_elb_writel(exynos_pcie, 0, PCIE_NONSTICKY_RESET); | 267 | exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_NONSTICKY_RESET); |
177 | } | 268 | } |
178 | 269 | ||
179 | static void exynos_pcie_deassert_core_reset(struct exynos_pcie *exynos_pcie) | 270 | static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep) |
180 | { | 271 | { |
181 | u32 val; | 272 | u32 val; |
182 | 273 | ||
183 | val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET); | 274 | val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); |
184 | val |= PCIE_CORE_RESET_ENABLE; | 275 | val |= PCIE_CORE_RESET_ENABLE; |
185 | 276 | ||
186 | exynos_elb_writel(exynos_pcie, val, PCIE_CORE_RESET); | 277 | exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET); |
187 | exynos_elb_writel(exynos_pcie, 1, PCIE_STICKY_RESET); | 278 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_STICKY_RESET); |
188 | exynos_elb_writel(exynos_pcie, 1, PCIE_NONSTICKY_RESET); | 279 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET); |
189 | exynos_elb_writel(exynos_pcie, 1, PCIE_APP_INIT_RESET); | 280 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET); |
190 | exynos_elb_writel(exynos_pcie, 0, PCIE_APP_INIT_RESET); | 281 | exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET); |
191 | exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_MAC_RESET); | 282 | exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_MAC_RESET); |
192 | } | 283 | } |
193 | 284 | ||
194 | static void exynos_pcie_assert_phy_reset(struct exynos_pcie *exynos_pcie) | 285 | static void exynos_pcie_assert_phy_reset(struct exynos_pcie *ep) |
195 | { | 286 | { |
196 | exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_MAC_RESET); | 287 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_MAC_RESET); |
197 | exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_GLOBAL_RESET); | 288 | exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_GLOBAL_RESET); |
198 | } | 289 | } |
199 | 290 | ||
200 | static void exynos_pcie_deassert_phy_reset(struct exynos_pcie *exynos_pcie) | 291 | static void exynos_pcie_deassert_phy_reset(struct exynos_pcie *ep) |
201 | { | 292 | { |
202 | exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_GLOBAL_RESET); | 293 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_GLOBAL_RESET); |
203 | exynos_elb_writel(exynos_pcie, 1, PCIE_PWR_RESET); | 294 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_PWR_RESET); |
204 | exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET); | 295 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_COMMON_RESET); |
205 | exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_CMN_REG); | 296 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_CMN_REG); |
206 | exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSVREG_RESET); | 297 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSVREG_RESET); |
207 | exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET); | 298 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSV_RESET); |
208 | } | 299 | } |
209 | 300 | ||
210 | static void exynos_pcie_power_on_phy(struct exynos_pcie *exynos_pcie) | 301 | static void exynos_pcie_power_on_phy(struct exynos_pcie *ep) |
211 | { | 302 | { |
212 | u32 val; | 303 | u32 val; |
213 | 304 | ||
214 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER); | 305 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER); |
215 | val &= ~PCIE_PHY_COMMON_PD_CMN; | 306 | val &= ~PCIE_PHY_COMMON_PD_CMN; |
216 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER); | 307 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER); |
217 | 308 | ||
218 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER); | 309 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER); |
219 | val &= ~PCIE_PHY_TRSV0_PD_TSV; | 310 | val &= ~PCIE_PHY_TRSV0_PD_TSV; |
220 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER); | 311 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER); |
221 | 312 | ||
222 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER); | 313 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER); |
223 | val &= ~PCIE_PHY_TRSV1_PD_TSV; | 314 | val &= ~PCIE_PHY_TRSV1_PD_TSV; |
224 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER); | 315 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER); |
225 | 316 | ||
226 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER); | 317 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER); |
227 | val &= ~PCIE_PHY_TRSV2_PD_TSV; | 318 | val &= ~PCIE_PHY_TRSV2_PD_TSV; |
228 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER); | 319 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER); |
229 | 320 | ||
230 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER); | 321 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER); |
231 | val &= ~PCIE_PHY_TRSV3_PD_TSV; | 322 | val &= ~PCIE_PHY_TRSV3_PD_TSV; |
232 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER); | 323 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER); |
233 | } | 324 | } |
234 | 325 | ||
235 | static void exynos_pcie_power_off_phy(struct exynos_pcie *exynos_pcie) | 326 | static void exynos_pcie_power_off_phy(struct exynos_pcie *ep) |
236 | { | 327 | { |
237 | u32 val; | 328 | u32 val; |
238 | 329 | ||
239 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER); | 330 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER); |
240 | val |= PCIE_PHY_COMMON_PD_CMN; | 331 | val |= PCIE_PHY_COMMON_PD_CMN; |
241 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER); | 332 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER); |
242 | 333 | ||
243 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER); | 334 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER); |
244 | val |= PCIE_PHY_TRSV0_PD_TSV; | 335 | val |= PCIE_PHY_TRSV0_PD_TSV; |
245 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER); | 336 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER); |
246 | 337 | ||
247 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER); | 338 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER); |
248 | val |= PCIE_PHY_TRSV1_PD_TSV; | 339 | val |= PCIE_PHY_TRSV1_PD_TSV; |
249 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER); | 340 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER); |
250 | 341 | ||
251 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER); | 342 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER); |
252 | val |= PCIE_PHY_TRSV2_PD_TSV; | 343 | val |= PCIE_PHY_TRSV2_PD_TSV; |
253 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER); | 344 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER); |
254 | 345 | ||
255 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER); | 346 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER); |
256 | val |= PCIE_PHY_TRSV3_PD_TSV; | 347 | val |= PCIE_PHY_TRSV3_PD_TSV; |
257 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER); | 348 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER); |
258 | } | 349 | } |
259 | 350 | ||
260 | static void exynos_pcie_init_phy(struct exynos_pcie *exynos_pcie) | 351 | static void exynos_pcie_init_phy(struct exynos_pcie *ep) |
261 | { | 352 | { |
262 | /* DCC feedback control off */ | 353 | /* DCC feedback control off */ |
263 | exynos_phy_writel(exynos_pcie, 0x29, PCIE_PHY_DCC_FEEDBACK); | 354 | exynos_pcie_writel(ep->mem_res->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK); |
264 | 355 | ||
265 | /* set TX/RX impedance */ | 356 | /* set TX/RX impedance */ |
266 | exynos_phy_writel(exynos_pcie, 0xd5, PCIE_PHY_IMPEDANCE); | 357 | exynos_pcie_writel(ep->mem_res->phy_base, 0xd5, PCIE_PHY_IMPEDANCE); |
267 | 358 | ||
268 | /* set 50Mhz PHY clock */ | 359 | /* set 50Mhz PHY clock */ |
269 | exynos_phy_writel(exynos_pcie, 0x14, PCIE_PHY_PLL_DIV_0); | 360 | exynos_pcie_writel(ep->mem_res->phy_base, 0x14, PCIE_PHY_PLL_DIV_0); |
270 | exynos_phy_writel(exynos_pcie, 0x12, PCIE_PHY_PLL_DIV_1); | 361 | exynos_pcie_writel(ep->mem_res->phy_base, 0x12, PCIE_PHY_PLL_DIV_1); |
271 | 362 | ||
272 | /* set TX Differential output for lane 0 */ | 363 | /* set TX Differential output for lane 0 */ |
273 | exynos_phy_writel(exynos_pcie, 0x7f, PCIE_PHY_TRSV0_DRV_LVL); | 364 | exynos_pcie_writel(ep->mem_res->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL); |
274 | 365 | ||
275 | /* set TX Pre-emphasis Level Control for lane 0 to minimum */ | 366 | /* set TX Pre-emphasis Level Control for lane 0 to minimum */ |
276 | exynos_phy_writel(exynos_pcie, 0x0, PCIE_PHY_TRSV0_EMP_LVL); | 367 | exynos_pcie_writel(ep->mem_res->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL); |
277 | 368 | ||
278 | /* set RX clock and data recovery bandwidth */ | 369 | /* set RX clock and data recovery bandwidth */ |
279 | exynos_phy_writel(exynos_pcie, 0xe7, PCIE_PHY_PLL_BIAS); | 370 | exynos_pcie_writel(ep->mem_res->phy_base, 0xe7, PCIE_PHY_PLL_BIAS); |
280 | exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV0_RXCDR); | 371 | exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR); |
281 | exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV1_RXCDR); | 372 | exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR); |
282 | exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV2_RXCDR); | 373 | exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR); |
283 | exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV3_RXCDR); | 374 | exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR); |
284 | 375 | ||
285 | /* change TX Pre-emphasis Level Control for lanes */ | 376 | /* change TX Pre-emphasis Level Control for lanes */ |
286 | exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV0_EMP_LVL); | 377 | exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL); |
287 | exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV1_EMP_LVL); | 378 | exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL); |
288 | exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV2_EMP_LVL); | 379 | exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL); |
289 | exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV3_EMP_LVL); | 380 | exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL); |
290 | 381 | ||
291 | /* set LVCC */ | 382 | /* set LVCC */ |
292 | exynos_phy_writel(exynos_pcie, 0x20, PCIE_PHY_TRSV0_LVCC); | 383 | exynos_pcie_writel(ep->mem_res->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC); |
293 | exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV1_LVCC); | 384 | exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC); |
294 | exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV2_LVCC); | 385 | exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC); |
295 | exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV3_LVCC); | 386 | exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC); |
296 | } | 387 | } |
297 | 388 | ||
298 | static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie) | 389 | static void exynos_pcie_assert_reset(struct exynos_pcie *ep) |
299 | { | 390 | { |
300 | struct dw_pcie *pci = exynos_pcie->pci; | 391 | struct dw_pcie *pci = ep->pci; |
301 | struct device *dev = pci->dev; | 392 | struct device *dev = pci->dev; |
302 | 393 | ||
303 | if (exynos_pcie->reset_gpio >= 0) | 394 | if (ep->reset_gpio >= 0) |
304 | devm_gpio_request_one(dev, exynos_pcie->reset_gpio, | 395 | devm_gpio_request_one(dev, ep->reset_gpio, |
305 | GPIOF_OUT_INIT_HIGH, "RESET"); | 396 | GPIOF_OUT_INIT_HIGH, "RESET"); |
306 | } | 397 | } |
307 | 398 | ||
308 | static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie) | 399 | static int exynos_pcie_establish_link(struct exynos_pcie *ep) |
309 | { | 400 | { |
310 | struct dw_pcie *pci = exynos_pcie->pci; | 401 | struct dw_pcie *pci = ep->pci; |
311 | struct pcie_port *pp = &pci->pp; | 402 | struct pcie_port *pp = &pci->pp; |
312 | struct device *dev = pci->dev; | 403 | struct device *dev = pci->dev; |
313 | u32 val; | 404 | u32 val; |
@@ -317,124 +408,149 @@ static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie) | |||
317 | return 0; | 408 | return 0; |
318 | } | 409 | } |
319 | 410 | ||
320 | exynos_pcie_assert_core_reset(exynos_pcie); | 411 | exynos_pcie_assert_core_reset(ep); |
321 | exynos_pcie_assert_phy_reset(exynos_pcie); | 412 | |
322 | exynos_pcie_deassert_phy_reset(exynos_pcie); | 413 | if (ep->using_phy) { |
323 | exynos_pcie_power_on_phy(exynos_pcie); | 414 | phy_reset(ep->phy); |
324 | exynos_pcie_init_phy(exynos_pcie); | 415 | |
416 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, | ||
417 | PCIE_PWR_RESET); | ||
418 | |||
419 | phy_power_on(ep->phy); | ||
420 | phy_init(ep->phy); | ||
421 | } else { | ||
422 | exynos_pcie_assert_phy_reset(ep); | ||
423 | exynos_pcie_deassert_phy_reset(ep); | ||
424 | exynos_pcie_power_on_phy(ep); | ||
425 | exynos_pcie_init_phy(ep); | ||
426 | |||
427 | /* pulse for common reset */ | ||
428 | exynos_pcie_writel(ep->mem_res->block_base, 1, | ||
429 | PCIE_PHY_COMMON_RESET); | ||
430 | udelay(500); | ||
431 | exynos_pcie_writel(ep->mem_res->block_base, 0, | ||
432 | PCIE_PHY_COMMON_RESET); | ||
433 | } | ||
325 | 434 | ||
326 | /* pulse for common reset */ | 435 | /* pulse for common reset */ |
327 | exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_COMMON_RESET); | 436 | exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_COMMON_RESET); |
328 | udelay(500); | 437 | udelay(500); |
329 | exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET); | 438 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_COMMON_RESET); |
330 | 439 | ||
331 | exynos_pcie_deassert_core_reset(exynos_pcie); | 440 | exynos_pcie_deassert_core_reset(ep); |
332 | dw_pcie_setup_rc(pp); | 441 | dw_pcie_setup_rc(pp); |
333 | exynos_pcie_assert_reset(exynos_pcie); | 442 | exynos_pcie_assert_reset(ep); |
334 | 443 | ||
335 | /* assert LTSSM enable */ | 444 | /* assert LTSSM enable */ |
336 | exynos_elb_writel(exynos_pcie, PCIE_ELBI_LTSSM_ENABLE, | 445 | exynos_pcie_writel(ep->mem_res->elbi_base, PCIE_ELBI_LTSSM_ENABLE, |
337 | PCIE_APP_LTSSM_ENABLE); | 446 | PCIE_APP_LTSSM_ENABLE); |
338 | 447 | ||
339 | /* check if the link is up or not */ | 448 | /* check if the link is up or not */ |
340 | if (!dw_pcie_wait_for_link(pci)) | 449 | if (!dw_pcie_wait_for_link(pci)) |
341 | return 0; | 450 | return 0; |
342 | 451 | ||
343 | while (exynos_phy_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED) == 0) { | 452 | if (ep->using_phy) { |
344 | val = exynos_blk_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED); | 453 | phy_power_off(ep->phy); |
454 | return -ETIMEDOUT; | ||
455 | } | ||
456 | |||
457 | while (exynos_pcie_readl(ep->mem_res->phy_base, | ||
458 | PCIE_PHY_PLL_LOCKED) == 0) { | ||
459 | val = exynos_pcie_readl(ep->mem_res->block_base, | ||
460 | PCIE_PHY_PLL_LOCKED); | ||
345 | dev_info(dev, "PLL Locked: 0x%x\n", val); | 461 | dev_info(dev, "PLL Locked: 0x%x\n", val); |
346 | } | 462 | } |
347 | exynos_pcie_power_off_phy(exynos_pcie); | 463 | exynos_pcie_power_off_phy(ep); |
348 | return -ETIMEDOUT; | 464 | return -ETIMEDOUT; |
349 | } | 465 | } |
350 | 466 | ||
351 | static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *exynos_pcie) | 467 | static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep) |
352 | { | 468 | { |
353 | u32 val; | 469 | u32 val; |
354 | 470 | ||
355 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE); | 471 | val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_PULSE); |
356 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE); | 472 | exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_PULSE); |
357 | } | 473 | } |
358 | 474 | ||
359 | static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *exynos_pcie) | 475 | static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep) |
360 | { | 476 | { |
361 | u32 val; | 477 | u32 val; |
362 | 478 | ||
363 | /* enable INTX interrupt */ | 479 | /* enable INTX interrupt */ |
364 | val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | | 480 | val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | |
365 | IRQ_INTC_ASSERT | IRQ_INTD_ASSERT; | 481 | IRQ_INTC_ASSERT | IRQ_INTD_ASSERT; |
366 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE); | 482 | exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_PULSE); |
367 | } | 483 | } |
368 | 484 | ||
369 | static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) | 485 | static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) |
370 | { | 486 | { |
371 | struct exynos_pcie *exynos_pcie = arg; | 487 | struct exynos_pcie *ep = arg; |
372 | 488 | ||
373 | exynos_pcie_clear_irq_pulse(exynos_pcie); | 489 | exynos_pcie_clear_irq_pulse(ep); |
374 | return IRQ_HANDLED; | 490 | return IRQ_HANDLED; |
375 | } | 491 | } |
376 | 492 | ||
377 | static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg) | 493 | static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg) |
378 | { | 494 | { |
379 | struct exynos_pcie *exynos_pcie = arg; | 495 | struct exynos_pcie *ep = arg; |
380 | struct dw_pcie *pci = exynos_pcie->pci; | 496 | struct dw_pcie *pci = ep->pci; |
381 | struct pcie_port *pp = &pci->pp; | 497 | struct pcie_port *pp = &pci->pp; |
382 | 498 | ||
383 | return dw_handle_msi_irq(pp); | 499 | return dw_handle_msi_irq(pp); |
384 | } | 500 | } |
385 | 501 | ||
386 | static void exynos_pcie_msi_init(struct exynos_pcie *exynos_pcie) | 502 | static void exynos_pcie_msi_init(struct exynos_pcie *ep) |
387 | { | 503 | { |
388 | struct dw_pcie *pci = exynos_pcie->pci; | 504 | struct dw_pcie *pci = ep->pci; |
389 | struct pcie_port *pp = &pci->pp; | 505 | struct pcie_port *pp = &pci->pp; |
390 | u32 val; | 506 | u32 val; |
391 | 507 | ||
392 | dw_pcie_msi_init(pp); | 508 | dw_pcie_msi_init(pp); |
393 | 509 | ||
394 | /* enable MSI interrupt */ | 510 | /* enable MSI interrupt */ |
395 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL); | 511 | val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL); |
396 | val |= IRQ_MSI_ENABLE; | 512 | val |= IRQ_MSI_ENABLE; |
397 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL); | 513 | exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL); |
398 | } | 514 | } |
399 | 515 | ||
400 | static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie) | 516 | static void exynos_pcie_enable_interrupts(struct exynos_pcie *ep) |
401 | { | 517 | { |
402 | exynos_pcie_enable_irq_pulse(exynos_pcie); | 518 | exynos_pcie_enable_irq_pulse(ep); |
403 | 519 | ||
404 | if (IS_ENABLED(CONFIG_PCI_MSI)) | 520 | if (IS_ENABLED(CONFIG_PCI_MSI)) |
405 | exynos_pcie_msi_init(exynos_pcie); | 521 | exynos_pcie_msi_init(ep); |
406 | } | 522 | } |
407 | 523 | ||
408 | static u32 exynos_pcie_readl_dbi(struct dw_pcie *pci, u32 reg) | 524 | static u32 exynos_pcie_readl_dbi(struct dw_pcie *pci, u32 reg) |
409 | { | 525 | { |
410 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); | 526 | struct exynos_pcie *ep = to_exynos_pcie(pci); |
411 | u32 val; | 527 | u32 val; |
412 | 528 | ||
413 | exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true); | 529 | exynos_pcie_sideband_dbi_r_mode(ep, true); |
414 | val = readl(pci->dbi_base + reg); | 530 | val = readl(pci->dbi_base + reg); |
415 | exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false); | 531 | exynos_pcie_sideband_dbi_r_mode(ep, false); |
416 | return val; | 532 | return val; |
417 | } | 533 | } |
418 | 534 | ||
419 | static void exynos_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val) | 535 | static void exynos_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val) |
420 | { | 536 | { |
421 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); | 537 | struct exynos_pcie *ep = to_exynos_pcie(pci); |
422 | 538 | ||
423 | exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true); | 539 | exynos_pcie_sideband_dbi_w_mode(ep, true); |
424 | writel(val, pci->dbi_base + reg); | 540 | writel(val, pci->dbi_base + reg); |
425 | exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false); | 541 | exynos_pcie_sideband_dbi_w_mode(ep, false); |
426 | } | 542 | } |
427 | 543 | ||
428 | static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | 544 | static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, |
429 | u32 *val) | 545 | u32 *val) |
430 | { | 546 | { |
431 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 547 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
432 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); | 548 | struct exynos_pcie *ep = to_exynos_pcie(pci); |
433 | int ret; | 549 | int ret; |
434 | 550 | ||
435 | exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true); | 551 | exynos_pcie_sideband_dbi_r_mode(ep, true); |
436 | ret = dw_pcie_read(pci->dbi_base + where, size, val); | 552 | ret = dw_pcie_read(pci->dbi_base + where, size, val); |
437 | exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false); | 553 | exynos_pcie_sideband_dbi_r_mode(ep, false); |
438 | return ret; | 554 | return ret; |
439 | } | 555 | } |
440 | 556 | ||
@@ -442,21 +558,21 @@ static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, | |||
442 | u32 val) | 558 | u32 val) |
443 | { | 559 | { |
444 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 560 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
445 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); | 561 | struct exynos_pcie *ep = to_exynos_pcie(pci); |
446 | int ret; | 562 | int ret; |
447 | 563 | ||
448 | exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true); | 564 | exynos_pcie_sideband_dbi_w_mode(ep, true); |
449 | ret = dw_pcie_write(pci->dbi_base + where, size, val); | 565 | ret = dw_pcie_write(pci->dbi_base + where, size, val); |
450 | exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false); | 566 | exynos_pcie_sideband_dbi_w_mode(ep, false); |
451 | return ret; | 567 | return ret; |
452 | } | 568 | } |
453 | 569 | ||
454 | static int exynos_pcie_link_up(struct dw_pcie *pci) | 570 | static int exynos_pcie_link_up(struct dw_pcie *pci) |
455 | { | 571 | { |
456 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); | 572 | struct exynos_pcie *ep = to_exynos_pcie(pci); |
457 | u32 val; | 573 | u32 val; |
458 | 574 | ||
459 | val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_RDLH_LINKUP); | 575 | val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_RDLH_LINKUP); |
460 | if (val == PCIE_ELBI_LTSSM_ENABLE) | 576 | if (val == PCIE_ELBI_LTSSM_ENABLE) |
461 | return 1; | 577 | return 1; |
462 | 578 | ||
@@ -466,10 +582,10 @@ static int exynos_pcie_link_up(struct dw_pcie *pci) | |||
466 | static void exynos_pcie_host_init(struct pcie_port *pp) | 582 | static void exynos_pcie_host_init(struct pcie_port *pp) |
467 | { | 583 | { |
468 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 584 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
469 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); | 585 | struct exynos_pcie *ep = to_exynos_pcie(pci); |
470 | 586 | ||
471 | exynos_pcie_establish_link(exynos_pcie); | 587 | exynos_pcie_establish_link(ep); |
472 | exynos_pcie_enable_interrupts(exynos_pcie); | 588 | exynos_pcie_enable_interrupts(ep); |
473 | } | 589 | } |
474 | 590 | ||
475 | static struct dw_pcie_host_ops exynos_pcie_host_ops = { | 591 | static struct dw_pcie_host_ops exynos_pcie_host_ops = { |
@@ -478,10 +594,10 @@ static struct dw_pcie_host_ops exynos_pcie_host_ops = { | |||
478 | .host_init = exynos_pcie_host_init, | 594 | .host_init = exynos_pcie_host_init, |
479 | }; | 595 | }; |
480 | 596 | ||
481 | static int __init exynos_add_pcie_port(struct exynos_pcie *exynos_pcie, | 597 | static int __init exynos_add_pcie_port(struct exynos_pcie *ep, |
482 | struct platform_device *pdev) | 598 | struct platform_device *pdev) |
483 | { | 599 | { |
484 | struct dw_pcie *pci = exynos_pcie->pci; | 600 | struct dw_pcie *pci = ep->pci; |
485 | struct pcie_port *pp = &pci->pp; | 601 | struct pcie_port *pp = &pci->pp; |
486 | struct device *dev = &pdev->dev; | 602 | struct device *dev = &pdev->dev; |
487 | int ret; | 603 | int ret; |
@@ -492,7 +608,7 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *exynos_pcie, | |||
492 | return -ENODEV; | 608 | return -ENODEV; |
493 | } | 609 | } |
494 | ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler, | 610 | ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler, |
495 | IRQF_SHARED, "exynos-pcie", exynos_pcie); | 611 | IRQF_SHARED, "exynos-pcie", ep); |
496 | if (ret) { | 612 | if (ret) { |
497 | dev_err(dev, "failed to request irq\n"); | 613 | dev_err(dev, "failed to request irq\n"); |
498 | return ret; | 614 | return ret; |
@@ -508,7 +624,7 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *exynos_pcie, | |||
508 | ret = devm_request_irq(dev, pp->msi_irq, | 624 | ret = devm_request_irq(dev, pp->msi_irq, |
509 | exynos_pcie_msi_irq_handler, | 625 | exynos_pcie_msi_irq_handler, |
510 | IRQF_SHARED | IRQF_NO_THREAD, | 626 | IRQF_SHARED | IRQF_NO_THREAD, |
511 | "exynos-pcie", exynos_pcie); | 627 | "exynos-pcie", ep); |
512 | if (ret) { | 628 | if (ret) { |
513 | dev_err(dev, "failed to request msi irq\n"); | 629 | dev_err(dev, "failed to request msi irq\n"); |
514 | return ret; | 630 | return ret; |
@@ -537,15 +653,12 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
537 | { | 653 | { |
538 | struct device *dev = &pdev->dev; | 654 | struct device *dev = &pdev->dev; |
539 | struct dw_pcie *pci; | 655 | struct dw_pcie *pci; |
540 | struct exynos_pcie *exynos_pcie; | 656 | struct exynos_pcie *ep; |
541 | struct device_node *np = dev->of_node; | 657 | struct device_node *np = dev->of_node; |
542 | struct resource *elbi_base; | ||
543 | struct resource *phy_base; | ||
544 | struct resource *block_base; | ||
545 | int ret; | 658 | int ret; |
546 | 659 | ||
547 | exynos_pcie = devm_kzalloc(dev, sizeof(*exynos_pcie), GFP_KERNEL); | 660 | ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); |
548 | if (!exynos_pcie) | 661 | if (!ep) |
549 | return -ENOMEM; | 662 | return -ENOMEM; |
550 | 663 | ||
551 | pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); | 664 | pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); |
@@ -555,75 +668,69 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
555 | pci->dev = dev; | 668 | pci->dev = dev; |
556 | pci->ops = &dw_pcie_ops; | 669 | pci->ops = &dw_pcie_ops; |
557 | 670 | ||
558 | exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); | 671 | ep->ops = (const struct exynos_pcie_ops *) |
672 | of_device_get_match_data(dev); | ||
559 | 673 | ||
560 | exynos_pcie->clk = devm_clk_get(dev, "pcie"); | 674 | ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); |
561 | if (IS_ERR(exynos_pcie->clk)) { | ||
562 | dev_err(dev, "Failed to get pcie rc clock\n"); | ||
563 | return PTR_ERR(exynos_pcie->clk); | ||
564 | } | ||
565 | ret = clk_prepare_enable(exynos_pcie->clk); | ||
566 | if (ret) | ||
567 | return ret; | ||
568 | 675 | ||
569 | exynos_pcie->bus_clk = devm_clk_get(dev, "pcie_bus"); | 676 | /* Assume that controller doesn't use the PHY framework */ |
570 | if (IS_ERR(exynos_pcie->bus_clk)) { | 677 | ep->using_phy = false; |
571 | dev_err(dev, "Failed to get pcie bus clock\n"); | ||
572 | ret = PTR_ERR(exynos_pcie->bus_clk); | ||
573 | goto fail_clk; | ||
574 | } | ||
575 | ret = clk_prepare_enable(exynos_pcie->bus_clk); | ||
576 | if (ret) | ||
577 | goto fail_clk; | ||
578 | |||
579 | elbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
580 | exynos_pcie->elbi_base = devm_ioremap_resource(dev, elbi_base); | ||
581 | if (IS_ERR(exynos_pcie->elbi_base)) { | ||
582 | ret = PTR_ERR(exynos_pcie->elbi_base); | ||
583 | goto fail_bus_clk; | ||
584 | } | ||
585 | 678 | ||
586 | phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 679 | ep->phy = devm_of_phy_get(dev, np, NULL); |
587 | exynos_pcie->phy_base = devm_ioremap_resource(dev, phy_base); | 680 | if (IS_ERR(ep->phy)) { |
588 | if (IS_ERR(exynos_pcie->phy_base)) { | 681 | if (PTR_ERR(ep->phy) == -EPROBE_DEFER) |
589 | ret = PTR_ERR(exynos_pcie->phy_base); | 682 | return PTR_ERR(ep->phy); |
590 | goto fail_bus_clk; | 683 | dev_warn(dev, "Use the 'phy' property. Current DT of pci-exynos was deprecated!!\n"); |
684 | } else | ||
685 | ep->using_phy = true; | ||
686 | |||
687 | if (ep->ops && ep->ops->get_mem_resources) { | ||
688 | ret = ep->ops->get_mem_resources(pdev, ep); | ||
689 | if (ret) | ||
690 | return ret; | ||
591 | } | 691 | } |
592 | 692 | ||
593 | block_base = platform_get_resource(pdev, IORESOURCE_MEM, 2); | 693 | if (ep->ops && ep->ops->get_clk_resources) { |
594 | exynos_pcie->block_base = devm_ioremap_resource(dev, block_base); | 694 | ret = ep->ops->get_clk_resources(ep); |
595 | if (IS_ERR(exynos_pcie->block_base)) { | 695 | if (ret) |
596 | ret = PTR_ERR(exynos_pcie->block_base); | 696 | return ret; |
597 | goto fail_bus_clk; | 697 | ret = ep->ops->init_clk_resources(ep); |
698 | if (ret) | ||
699 | return ret; | ||
598 | } | 700 | } |
599 | 701 | ||
600 | platform_set_drvdata(pdev, exynos_pcie); | 702 | platform_set_drvdata(pdev, ep); |
601 | 703 | ||
602 | ret = exynos_add_pcie_port(exynos_pcie, pdev); | 704 | ret = exynos_add_pcie_port(ep, pdev); |
603 | if (ret < 0) | 705 | if (ret < 0) |
604 | goto fail_bus_clk; | 706 | goto fail_probe; |
605 | 707 | ||
606 | return 0; | 708 | return 0; |
607 | 709 | ||
608 | fail_bus_clk: | 710 | fail_probe: |
609 | clk_disable_unprepare(exynos_pcie->bus_clk); | 711 | if (ep->using_phy) |
610 | fail_clk: | 712 | phy_exit(ep->phy); |
611 | clk_disable_unprepare(exynos_pcie->clk); | 713 | |
714 | if (ep->ops && ep->ops->deinit_clk_resources) | ||
715 | ep->ops->deinit_clk_resources(ep); | ||
612 | return ret; | 716 | return ret; |
613 | } | 717 | } |
614 | 718 | ||
615 | static int __exit exynos_pcie_remove(struct platform_device *pdev) | 719 | static int __exit exynos_pcie_remove(struct platform_device *pdev) |
616 | { | 720 | { |
617 | struct exynos_pcie *exynos_pcie = platform_get_drvdata(pdev); | 721 | struct exynos_pcie *ep = platform_get_drvdata(pdev); |
618 | 722 | ||
619 | clk_disable_unprepare(exynos_pcie->bus_clk); | 723 | if (ep->ops && ep->ops->deinit_clk_resources) |
620 | clk_disable_unprepare(exynos_pcie->clk); | 724 | ep->ops->deinit_clk_resources(ep); |
621 | 725 | ||
622 | return 0; | 726 | return 0; |
623 | } | 727 | } |
624 | 728 | ||
625 | static const struct of_device_id exynos_pcie_of_match[] = { | 729 | static const struct of_device_id exynos_pcie_of_match[] = { |
626 | { .compatible = "samsung,exynos5440-pcie", }, | 730 | { |
731 | .compatible = "samsung,exynos5440-pcie", | ||
732 | .data = &exynos5440_pcie_ops | ||
733 | }, | ||
627 | {}, | 734 | {}, |
628 | }; | 735 | }; |
629 | 736 | ||
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index e8eb7f225a88..bbad035c60cc 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -331,6 +331,14 @@ config PHY_EXYNOS5_USBDRD | |||
331 | This driver provides PHY interface for USB 3.0 DRD controller | 331 | This driver provides PHY interface for USB 3.0 DRD controller |
332 | present on Exynos5 SoC series. | 332 | present on Exynos5 SoC series. |
333 | 333 | ||
334 | config PHY_EXYNOS_PCIE | ||
335 | bool "Exynos PCIe PHY driver" | ||
336 | depends on OF && (ARCH_EXYNOS || COMPILE_TEST) | ||
337 | select GENERIC_PHY | ||
338 | help | ||
339 | Enable PCIe PHY support for Exynos SoC series. | ||
340 | This driver provides PHY interface for Exynos PCIe controller. | ||
341 | |||
334 | config PHY_PISTACHIO_USB | 342 | config PHY_PISTACHIO_USB |
335 | tristate "IMG Pistachio USB2.0 PHY driver" | 343 | tristate "IMG Pistachio USB2.0 PHY driver" |
336 | depends on MACH_PISTACHIO | 344 | depends on MACH_PISTACHIO |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 65eb2f436a41..081aeb4efd13 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -37,6 +37,7 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o | |||
37 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o | 37 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o |
38 | phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o | 38 | phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o |
39 | obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o | 39 | obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o |
40 | obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o | ||
40 | obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o | 41 | obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o |
41 | obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o | 42 | obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o |
42 | obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o | 43 | obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o |
diff --git a/drivers/phy/phy-exynos-pcie.c b/drivers/phy/phy-exynos-pcie.c new file mode 100644 index 000000000000..4f60b83641d5 --- /dev/null +++ b/drivers/phy/phy-exynos-pcie.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * Samsung EXYNOS SoC series PCIe PHY driver | ||
3 | * | ||
4 | * Phy provider for PCIe controller on Exynos SoC series | ||
5 | * | ||
6 | * Copyright (C) 2017 Samsung Electronics Co., Ltd. | ||
7 | * Jaehoon Chung <jh80.chung@samsung.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/iopoll.h> | ||
17 | #include <linux/mfd/syscon.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_address.h> | ||
21 | #include <linux/of_platform.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/phy/phy.h> | ||
24 | #include <linux/regmap.h> | ||
25 | |||
26 | /* PCIe Purple registers */ | ||
27 | #define PCIE_PHY_GLOBAL_RESET 0x000 | ||
28 | #define PCIE_PHY_COMMON_RESET 0x004 | ||
29 | #define PCIE_PHY_CMN_REG 0x008 | ||
30 | #define PCIE_PHY_MAC_RESET 0x00c | ||
31 | #define PCIE_PHY_PLL_LOCKED 0x010 | ||
32 | #define PCIE_PHY_TRSVREG_RESET 0x020 | ||
33 | #define PCIE_PHY_TRSV_RESET 0x024 | ||
34 | |||
35 | /* PCIe PHY registers */ | ||
36 | #define PCIE_PHY_IMPEDANCE 0x004 | ||
37 | #define PCIE_PHY_PLL_DIV_0 0x008 | ||
38 | #define PCIE_PHY_PLL_BIAS 0x00c | ||
39 | #define PCIE_PHY_DCC_FEEDBACK 0x014 | ||
40 | #define PCIE_PHY_PLL_DIV_1 0x05c | ||
41 | #define PCIE_PHY_COMMON_POWER 0x064 | ||
42 | #define PCIE_PHY_COMMON_PD_CMN BIT(3) | ||
43 | #define PCIE_PHY_TRSV0_EMP_LVL 0x084 | ||
44 | #define PCIE_PHY_TRSV0_DRV_LVL 0x088 | ||
45 | #define PCIE_PHY_TRSV0_RXCDR 0x0ac | ||
46 | #define PCIE_PHY_TRSV0_POWER 0x0c4 | ||
47 | #define PCIE_PHY_TRSV0_PD_TSV BIT(7) | ||
48 | #define PCIE_PHY_TRSV0_LVCC 0x0dc | ||
49 | #define PCIE_PHY_TRSV1_EMP_LVL 0x144 | ||
50 | #define PCIE_PHY_TRSV1_RXCDR 0x16c | ||
51 | #define PCIE_PHY_TRSV1_POWER 0x184 | ||
52 | #define PCIE_PHY_TRSV1_PD_TSV BIT(7) | ||
53 | #define PCIE_PHY_TRSV1_LVCC 0x19c | ||
54 | #define PCIE_PHY_TRSV2_EMP_LVL 0x204 | ||
55 | #define PCIE_PHY_TRSV2_RXCDR 0x22c | ||
56 | #define PCIE_PHY_TRSV2_POWER 0x244 | ||
57 | #define PCIE_PHY_TRSV2_PD_TSV BIT(7) | ||
58 | #define PCIE_PHY_TRSV2_LVCC 0x25c | ||
59 | #define PCIE_PHY_TRSV3_EMP_LVL 0x2c4 | ||
60 | #define PCIE_PHY_TRSV3_RXCDR 0x2ec | ||
61 | #define PCIE_PHY_TRSV3_POWER 0x304 | ||
62 | #define PCIE_PHY_TRSV3_PD_TSV BIT(7) | ||
63 | #define PCIE_PHY_TRSV3_LVCC 0x31c | ||
64 | |||
65 | struct exynos_pcie_phy_data { | ||
66 | const struct phy_ops *ops; | ||
67 | }; | ||
68 | |||
69 | /* For Exynos pcie phy */ | ||
70 | struct exynos_pcie_phy { | ||
71 | const struct exynos_pcie_phy_data *drv_data; | ||
72 | void __iomem *phy_base; | ||
73 | void __iomem *blk_base; /* For exynos5440 */ | ||
74 | }; | ||
75 | |||
76 | static void exynos_pcie_phy_writel(void __iomem *base, u32 val, u32 offset) | ||
77 | { | ||
78 | writel(val, base + offset); | ||
79 | } | ||
80 | |||
81 | static u32 exynos_pcie_phy_readl(void __iomem *base, u32 offset) | ||
82 | { | ||
83 | return readl(base + offset); | ||
84 | } | ||
85 | |||
86 | /* For Exynos5440 specific functions */ | ||
87 | static int exynos5440_pcie_phy_init(struct phy *phy) | ||
88 | { | ||
89 | struct exynos_pcie_phy *ep = phy_get_drvdata(phy); | ||
90 | |||
91 | /* DCC feedback control off */ | ||
92 | exynos_pcie_phy_writel(ep->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK); | ||
93 | |||
94 | /* set TX/RX impedance */ | ||
95 | exynos_pcie_phy_writel(ep->phy_base, 0xd5, PCIE_PHY_IMPEDANCE); | ||
96 | |||
97 | /* set 50Mhz PHY clock */ | ||
98 | exynos_pcie_phy_writel(ep->phy_base, 0x14, PCIE_PHY_PLL_DIV_0); | ||
99 | exynos_pcie_phy_writel(ep->phy_base, 0x12, PCIE_PHY_PLL_DIV_1); | ||
100 | |||
101 | /* set TX Differential output for lane 0 */ | ||
102 | exynos_pcie_phy_writel(ep->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL); | ||
103 | |||
104 | /* set TX Pre-emphasis Level Control for lane 0 to minimum */ | ||
105 | exynos_pcie_phy_writel(ep->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL); | ||
106 | |||
107 | /* set RX clock and data recovery bandwidth */ | ||
108 | exynos_pcie_phy_writel(ep->phy_base, 0xe7, PCIE_PHY_PLL_BIAS); | ||
109 | exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR); | ||
110 | exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR); | ||
111 | exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR); | ||
112 | exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR); | ||
113 | |||
114 | /* change TX Pre-emphasis Level Control for lanes */ | ||
115 | exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL); | ||
116 | exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL); | ||
117 | exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL); | ||
118 | exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL); | ||
119 | |||
120 | /* set LVCC */ | ||
121 | exynos_pcie_phy_writel(ep->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC); | ||
122 | exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC); | ||
123 | exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC); | ||
124 | exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC); | ||
125 | |||
126 | /* pulse for common reset */ | ||
127 | exynos_pcie_phy_writel(ep->blk_base, 1, PCIE_PHY_COMMON_RESET); | ||
128 | udelay(500); | ||
129 | exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_COMMON_RESET); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int exynos5440_pcie_phy_power_on(struct phy *phy) | ||
135 | { | ||
136 | struct exynos_pcie_phy *ep = phy_get_drvdata(phy); | ||
137 | u32 val; | ||
138 | |||
139 | exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_COMMON_RESET); | ||
140 | exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_CMN_REG); | ||
141 | exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_TRSVREG_RESET); | ||
142 | exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_TRSV_RESET); | ||
143 | |||
144 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_COMMON_POWER); | ||
145 | val &= ~PCIE_PHY_COMMON_PD_CMN; | ||
146 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER); | ||
147 | |||
148 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER); | ||
149 | val &= ~PCIE_PHY_TRSV0_PD_TSV; | ||
150 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER); | ||
151 | |||
152 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER); | ||
153 | val &= ~PCIE_PHY_TRSV1_PD_TSV; | ||
154 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER); | ||
155 | |||
156 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER); | ||
157 | val &= ~PCIE_PHY_TRSV2_PD_TSV; | ||
158 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER); | ||
159 | |||
160 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER); | ||
161 | val &= ~PCIE_PHY_TRSV3_PD_TSV; | ||
162 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int exynos5440_pcie_phy_power_off(struct phy *phy) | ||
168 | { | ||
169 | struct exynos_pcie_phy *ep = phy_get_drvdata(phy); | ||
170 | u32 val; | ||
171 | |||
172 | if (readl_poll_timeout(ep->phy_base + PCIE_PHY_PLL_LOCKED, val, | ||
173 | (val != 0), 1, 500)) { | ||
174 | dev_err(&phy->dev, "PLL Locked: 0x%x\n", val); | ||
175 | return -ETIMEDOUT; | ||
176 | } | ||
177 | |||
178 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_COMMON_POWER); | ||
179 | val |= PCIE_PHY_COMMON_PD_CMN; | ||
180 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER); | ||
181 | |||
182 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER); | ||
183 | val |= PCIE_PHY_TRSV0_PD_TSV; | ||
184 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER); | ||
185 | |||
186 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER); | ||
187 | val |= PCIE_PHY_TRSV1_PD_TSV; | ||
188 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER); | ||
189 | |||
190 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER); | ||
191 | val |= PCIE_PHY_TRSV2_PD_TSV; | ||
192 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER); | ||
193 | |||
194 | val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER); | ||
195 | val |= PCIE_PHY_TRSV3_PD_TSV; | ||
196 | exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int exynos5440_pcie_phy_reset(struct phy *phy) | ||
202 | { | ||
203 | struct exynos_pcie_phy *ep = phy_get_drvdata(phy); | ||
204 | |||
205 | exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_MAC_RESET); | ||
206 | exynos_pcie_phy_writel(ep->blk_base, 1, PCIE_PHY_GLOBAL_RESET); | ||
207 | exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_GLOBAL_RESET); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static const struct phy_ops exynos5440_phy_ops = { | ||
213 | .init = exynos5440_pcie_phy_init, | ||
214 | .power_on = exynos5440_pcie_phy_power_on, | ||
215 | .power_off = exynos5440_pcie_phy_power_off, | ||
216 | .reset = exynos5440_pcie_phy_reset, | ||
217 | .owner = THIS_MODULE, | ||
218 | }; | ||
219 | |||
220 | static const struct exynos_pcie_phy_data exynos5440_pcie_phy_data = { | ||
221 | .ops = &exynos5440_phy_ops, | ||
222 | }; | ||
223 | |||
224 | static const struct of_device_id exynos_pcie_phy_match[] = { | ||
225 | { | ||
226 | .compatible = "samsung,exynos5440-pcie-phy", | ||
227 | .data = &exynos5440_pcie_phy_data, | ||
228 | }, | ||
229 | {}, | ||
230 | }; | ||
231 | MODULE_DEVICE_TABLE(of, exynos_pcie_phy_match); | ||
232 | |||
233 | static int exynos_pcie_phy_probe(struct platform_device *pdev) | ||
234 | { | ||
235 | struct device *dev = &pdev->dev; | ||
236 | struct exynos_pcie_phy *exynos_phy; | ||
237 | struct phy *generic_phy; | ||
238 | struct phy_provider *phy_provider; | ||
239 | struct resource *res; | ||
240 | const struct exynos_pcie_phy_data *drv_data; | ||
241 | |||
242 | drv_data = of_device_get_match_data(dev); | ||
243 | if (!drv_data) | ||
244 | return -ENODEV; | ||
245 | |||
246 | exynos_phy = devm_kzalloc(dev, sizeof(*exynos_phy), GFP_KERNEL); | ||
247 | if (!exynos_phy) | ||
248 | return -ENOMEM; | ||
249 | |||
250 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
251 | exynos_phy->phy_base = devm_ioremap_resource(dev, res); | ||
252 | if (IS_ERR(exynos_phy->phy_base)) | ||
253 | return PTR_ERR(exynos_phy->phy_base); | ||
254 | |||
255 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
256 | exynos_phy->blk_base = devm_ioremap_resource(dev, res); | ||
257 | if (IS_ERR(exynos_phy->phy_base)) | ||
258 | return PTR_ERR(exynos_phy->phy_base); | ||
259 | |||
260 | exynos_phy->drv_data = drv_data; | ||
261 | |||
262 | generic_phy = devm_phy_create(dev, dev->of_node, drv_data->ops); | ||
263 | if (IS_ERR(generic_phy)) { | ||
264 | dev_err(dev, "failed to create PHY\n"); | ||
265 | return PTR_ERR(generic_phy); | ||
266 | } | ||
267 | |||
268 | phy_set_drvdata(generic_phy, exynos_phy); | ||
269 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
270 | |||
271 | return PTR_ERR_OR_ZERO(phy_provider); | ||
272 | } | ||
273 | |||
274 | static struct platform_driver exynos_pcie_phy_driver = { | ||
275 | .probe = exynos_pcie_phy_probe, | ||
276 | .driver = { | ||
277 | .of_match_table = exynos_pcie_phy_match, | ||
278 | .name = "exynos_pcie_phy", | ||
279 | } | ||
280 | }; | ||
281 | module_platform_driver(exynos_pcie_phy_driver); | ||
282 | |||
283 | MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC PCIe PHY driver"); | ||
284 | MODULE_AUTHOR("Jaehoon Chung <jh80.chung@samsung.com>"); | ||
285 | MODULE_LICENSE("GPL v2"); | ||