diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2017-09-07 14:24:07 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-09-07 14:24:07 -0400 |
commit | 68e8fa46d185894b6d1fe7f2f71a8a83b442c633 (patch) | |
tree | b27856d10e273c1e3680d0eeacc65f49f220f87f | |
parent | 3d499a955a30ef1bb9b2176ecb1d3a6be8e3ef9c (diff) | |
parent | 81edd471a61474de1ea772f27a3c734a68a09cc6 (diff) |
Merge branch 'pci/host-rockchip' into next
* pci/host-rockchip:
PCI: rockchip: Fix platform_get_irq() error handling
PCI: rockchip: Umap IO space if probe fails
PCI: rockchip: Remove IRQ domain if probe fails
PCI: rockchip: Disable vpcie0v9 if resume_noirq fails
PCI: rockchip: Clean up PHY if driver probe or resume fails
PCI: rockchip: Factor out rockchip_pcie_deinit_phys()
PCI: rockchip: Factor out rockchip_pcie_disable_clocks()
PCI: rockchip: Factor out rockchip_pcie_enable_clocks()
PCI: rockchip: Factor out rockchip_pcie_setup_irq()
PCI: rockchip: Use gpiod_set_value_cansleep() to allow reset via expanders
PCI: rockchip: Use PCI_NUM_INTX
PCI: rockchip: Explicitly request exclusive reset control
dt-bindings: phy-rockchip-pcie: Convert to per-lane PHY model
dt-bindings: PCI: rockchip: Convert to per-lane PHY model
arm64: dts: rockchip: convert PCIe to use per-lane PHYs for rk3339
PCI: rockchip: Idle inactive PHY(s)
phy: rockchip-pcie: Reconstruct driver to support per-lane PHYs
PCI: rockchip: Add per-lane PHY support
PCI: rockchip: Factor out rockchip_pcie_get_phys()
PCI: rockchip: Control optional 12v power supply
dt-bindings: PCI: rockchip: Add vpcie12v-supply for Rockchip PCIe controller
-rw-r--r-- | Documentation/devicetree/bindings/pci/rockchip-pcie.txt | 26 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt | 7 | ||||
-rw-r--r-- | arch/arm64/boot/dts/rockchip/rk3399.dtsi | 8 | ||||
-rw-r--r-- | drivers/pci/host/pcie-rockchip.c | 424 | ||||
-rw-r--r-- | drivers/phy/rockchip/phy-rockchip-pcie.c | 131 |
5 files changed, 433 insertions, 163 deletions
diff --git a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt index 1453a734c2f5..5678be82530d 100644 --- a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt +++ b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt | |||
@@ -19,8 +19,6 @@ Required properties: | |||
19 | - "pm" | 19 | - "pm" |
20 | - msi-map: Maps a Requester ID to an MSI controller and associated | 20 | - msi-map: Maps a Requester ID to an MSI controller and associated |
21 | msi-specifier data. See ./pci-msi.txt | 21 | msi-specifier data. See ./pci-msi.txt |
22 | - phys: From PHY bindings: Phandle for the Generic PHY for PCIe. | ||
23 | - phy-names: MUST be "pcie-phy". | ||
24 | - interrupts: Three interrupt entries must be specified. | 22 | - interrupts: Three interrupt entries must be specified. |
25 | - interrupt-names: Must include the following names | 23 | - interrupt-names: Must include the following names |
26 | - "sys" | 24 | - "sys" |
@@ -42,11 +40,24 @@ Required properties: | |||
42 | interrupt source. The value must be 1. | 40 | interrupt source. The value must be 1. |
43 | - interrupt-map-mask and interrupt-map: standard PCI properties | 41 | - interrupt-map-mask and interrupt-map: standard PCI properties |
44 | 42 | ||
43 | Required properties for legacy PHY model (deprecated): | ||
44 | - phys: From PHY bindings: Phandle for the Generic PHY for PCIe. | ||
45 | - phy-names: MUST be "pcie-phy". | ||
46 | |||
47 | Required properties for per-lane PHY model (preferred): | ||
48 | - phys: Must contain an phandle to a PHY for each entry in phy-names. | ||
49 | - phy-names: Must include 4 entries for all 4 lanes even if some of | ||
50 | them won't be used for your cases. Entries are of the form "pcie-phy-N": | ||
51 | where N ranges from 0 to 3. | ||
52 | (see example below and you MUST also refer to ../phy/rockchip-pcie-phy.txt | ||
53 | for changing the #phy-cells of phy node to support it) | ||
54 | |||
45 | Optional Property: | 55 | Optional Property: |
46 | - aspm-no-l0s: RC won't support ASPM L0s. This property is needed if | 56 | - aspm-no-l0s: RC won't support ASPM L0s. This property is needed if |
47 | using 24MHz OSC for RC's PHY. | 57 | using 24MHz OSC for RC's PHY. |
48 | - ep-gpios: contain the entry for pre-reset gpio | 58 | - ep-gpios: contain the entry for pre-reset gpio |
49 | - num-lanes: number of lanes to use | 59 | - num-lanes: number of lanes to use |
60 | - vpcie12v-supply: The phandle to the 12v regulator to use for PCIe. | ||
50 | - vpcie3v3-supply: The phandle to the 3.3v regulator to use for PCIe. | 61 | - vpcie3v3-supply: The phandle to the 3.3v regulator to use for PCIe. |
51 | - vpcie1v8-supply: The phandle to the 1.8v regulator to use for PCIe. | 62 | - vpcie1v8-supply: The phandle to the 1.8v regulator to use for PCIe. |
52 | - vpcie0v9-supply: The phandle to the 0.9v regulator to use for PCIe. | 63 | - vpcie0v9-supply: The phandle to the 0.9v regulator to use for PCIe. |
@@ -95,6 +106,7 @@ pcie0: pcie@f8000000 { | |||
95 | <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, <&cru SRST_A_PCIE>; | 106 | <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, <&cru SRST_A_PCIE>; |
96 | reset-names = "core", "mgmt", "mgmt-sticky", "pipe", | 107 | reset-names = "core", "mgmt", "mgmt-sticky", "pipe", |
97 | "pm", "pclk", "aclk"; | 108 | "pm", "pclk", "aclk"; |
109 | /* deprecated legacy PHY model */ | ||
98 | phys = <&pcie_phy>; | 110 | phys = <&pcie_phy>; |
99 | phy-names = "pcie-phy"; | 111 | phy-names = "pcie-phy"; |
100 | pinctrl-names = "default"; | 112 | pinctrl-names = "default"; |
@@ -111,3 +123,13 @@ pcie0: pcie@f8000000 { | |||
111 | #interrupt-cells = <1>; | 123 | #interrupt-cells = <1>; |
112 | }; | 124 | }; |
113 | }; | 125 | }; |
126 | |||
127 | pcie0: pcie@f8000000 { | ||
128 | ... | ||
129 | |||
130 | /* preferred per-lane PHY model */ | ||
131 | phys = <&pcie_phy 0>, <&pcie_phy 1>, <&pcie_phy 2>, <&pcie_phy 3>; | ||
132 | phy-names = "pcie-phy-0", "pcie-phy-1", "pcie-phy-2", "pcie-phy-3"; | ||
133 | |||
134 | ... | ||
135 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt index 0f6222a672ce..b496042f1f44 100644 --- a/Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt +++ b/Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt | |||
@@ -3,7 +3,6 @@ Rockchip PCIE PHY | |||
3 | 3 | ||
4 | Required properties: | 4 | Required properties: |
5 | - compatible: rockchip,rk3399-pcie-phy | 5 | - compatible: rockchip,rk3399-pcie-phy |
6 | - #phy-cells: must be 0 | ||
7 | - clocks: Must contain an entry in clock-names. | 6 | - clocks: Must contain an entry in clock-names. |
8 | See ../clocks/clock-bindings.txt for details. | 7 | See ../clocks/clock-bindings.txt for details. |
9 | - clock-names: Must be "refclk" | 8 | - clock-names: Must be "refclk" |
@@ -11,6 +10,12 @@ Required properties: | |||
11 | See ../reset/reset.txt for details. | 10 | See ../reset/reset.txt for details. |
12 | - reset-names: Must be "phy" | 11 | - reset-names: Must be "phy" |
13 | 12 | ||
13 | Required properties for legacy PHY mode (deprecated): | ||
14 | - #phy-cells: must be 0 | ||
15 | |||
16 | Required properties for per-lane PHY mode (preferred): | ||
17 | - #phy-cells: must be 1 | ||
18 | |||
14 | Example: | 19 | Example: |
15 | 20 | ||
16 | grf: syscon@ff770000 { | 21 | grf: syscon@ff770000 { |
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index 69c56f7316c4..5b78ce16a87e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi | |||
@@ -238,8 +238,10 @@ | |||
238 | linux,pci-domain = <0>; | 238 | linux,pci-domain = <0>; |
239 | max-link-speed = <1>; | 239 | max-link-speed = <1>; |
240 | msi-map = <0x0 &its 0x0 0x1000>; | 240 | msi-map = <0x0 &its 0x0 0x1000>; |
241 | phys = <&pcie_phy>; | 241 | phys = <&pcie_phy 0>, <&pcie_phy 1>, |
242 | phy-names = "pcie-phy"; | 242 | <&pcie_phy 2>, <&pcie_phy 3>; |
243 | phy-names = "pcie-phy-0", "pcie-phy-1", | ||
244 | "pcie-phy-2", "pcie-phy-3"; | ||
243 | ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x1e00000 | 245 | ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x1e00000 |
244 | 0x81000000 0x0 0xfbe00000 0x0 0xfbe00000 0x0 0x100000>; | 246 | 0x81000000 0x0 0xfbe00000 0x0 0xfbe00000 0x0 0x100000>; |
245 | resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>, | 247 | resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>, |
@@ -1295,7 +1297,7 @@ | |||
1295 | compatible = "rockchip,rk3399-pcie-phy"; | 1297 | compatible = "rockchip,rk3399-pcie-phy"; |
1296 | clocks = <&cru SCLK_PCIEPHY_REF>; | 1298 | clocks = <&cru SCLK_PCIEPHY_REF>; |
1297 | clock-names = "refclk"; | 1299 | clock-names = "refclk"; |
1298 | #phy-cells = <0>; | 1300 | #phy-cells = <1>; |
1299 | resets = <&cru SRST_PCIEPHY>; | 1301 | resets = <&cru SRST_PCIEPHY>; |
1300 | reset-names = "phy"; | 1302 | reset-names = "phy"; |
1301 | status = "disabled"; | 1303 | status = "disabled"; |
diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index 7bb9870f6d8c..d205381c7ec4 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * (at your option) any later version. | 15 | * (at your option) any later version. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/bitrev.h> | ||
18 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
19 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
20 | #include <linux/gpio/consumer.h> | 21 | #include <linux/gpio/consumer.h> |
@@ -47,6 +48,7 @@ | |||
47 | #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) | 48 | #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) |
48 | 49 | ||
49 | #define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4) | 50 | #define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4) |
51 | #define MAX_LANE_NUM 4 | ||
50 | 52 | ||
51 | #define PCIE_CLIENT_BASE 0x0 | 53 | #define PCIE_CLIENT_BASE 0x0 |
52 | #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) | 54 | #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) |
@@ -111,6 +113,9 @@ | |||
111 | #define PCIE_CORE_TXCREDIT_CFG1_MUI_SHIFT 16 | 113 | #define PCIE_CORE_TXCREDIT_CFG1_MUI_SHIFT 16 |
112 | #define PCIE_CORE_TXCREDIT_CFG1_MUI_ENCODE(x) \ | 114 | #define PCIE_CORE_TXCREDIT_CFG1_MUI_ENCODE(x) \ |
113 | (((x) >> 3) << PCIE_CORE_TXCREDIT_CFG1_MUI_SHIFT) | 115 | (((x) >> 3) << PCIE_CORE_TXCREDIT_CFG1_MUI_SHIFT) |
116 | #define PCIE_CORE_LANE_MAP (PCIE_CORE_CTRL_MGMT_BASE + 0x200) | ||
117 | #define PCIE_CORE_LANE_MAP_MASK 0x0000000f | ||
118 | #define PCIE_CORE_LANE_MAP_REVERSE BIT(16) | ||
114 | #define PCIE_CORE_INT_STATUS (PCIE_CORE_CTRL_MGMT_BASE + 0x20c) | 119 | #define PCIE_CORE_INT_STATUS (PCIE_CORE_CTRL_MGMT_BASE + 0x20c) |
115 | #define PCIE_CORE_INT_PRFPE BIT(0) | 120 | #define PCIE_CORE_INT_PRFPE BIT(0) |
116 | #define PCIE_CORE_INT_CRFPE BIT(1) | 121 | #define PCIE_CORE_INT_CRFPE BIT(1) |
@@ -210,7 +215,8 @@ | |||
210 | struct rockchip_pcie { | 215 | struct rockchip_pcie { |
211 | void __iomem *reg_base; /* DT axi-base */ | 216 | void __iomem *reg_base; /* DT axi-base */ |
212 | void __iomem *apb_base; /* DT apb-base */ | 217 | void __iomem *apb_base; /* DT apb-base */ |
213 | struct phy *phy; | 218 | bool legacy_phy; |
219 | struct phy *phys[MAX_LANE_NUM]; | ||
214 | struct reset_control *core_rst; | 220 | struct reset_control *core_rst; |
215 | struct reset_control *mgmt_rst; | 221 | struct reset_control *mgmt_rst; |
216 | struct reset_control *mgmt_sticky_rst; | 222 | struct reset_control *mgmt_sticky_rst; |
@@ -222,11 +228,13 @@ struct rockchip_pcie { | |||
222 | struct clk *aclk_perf_pcie; | 228 | struct clk *aclk_perf_pcie; |
223 | struct clk *hclk_pcie; | 229 | struct clk *hclk_pcie; |
224 | struct clk *clk_pcie_pm; | 230 | struct clk *clk_pcie_pm; |
231 | struct regulator *vpcie12v; /* 12V power supply */ | ||
225 | struct regulator *vpcie3v3; /* 3.3V power supply */ | 232 | struct regulator *vpcie3v3; /* 3.3V power supply */ |
226 | struct regulator *vpcie1v8; /* 1.8V power supply */ | 233 | struct regulator *vpcie1v8; /* 1.8V power supply */ |
227 | struct regulator *vpcie0v9; /* 0.9V power supply */ | 234 | struct regulator *vpcie0v9; /* 0.9V power supply */ |
228 | struct gpio_desc *ep_gpio; | 235 | struct gpio_desc *ep_gpio; |
229 | u32 lanes; | 236 | u32 lanes; |
237 | u8 lanes_map; | ||
230 | u8 root_bus_nr; | 238 | u8 root_bus_nr; |
231 | int link_gen; | 239 | int link_gen; |
232 | struct device *dev; | 240 | struct device *dev; |
@@ -299,6 +307,24 @@ static int rockchip_pcie_valid_device(struct rockchip_pcie *rockchip, | |||
299 | return 1; | 307 | return 1; |
300 | } | 308 | } |
301 | 309 | ||
310 | static u8 rockchip_pcie_lane_map(struct rockchip_pcie *rockchip) | ||
311 | { | ||
312 | u32 val; | ||
313 | u8 map; | ||
314 | |||
315 | if (rockchip->legacy_phy) | ||
316 | return GENMASK(MAX_LANE_NUM - 1, 0); | ||
317 | |||
318 | val = rockchip_pcie_read(rockchip, PCIE_CORE_LANE_MAP); | ||
319 | map = val & PCIE_CORE_LANE_MAP_MASK; | ||
320 | |||
321 | /* The link may be using a reverse-indexed mapping. */ | ||
322 | if (val & PCIE_CORE_LANE_MAP_REVERSE) | ||
323 | map = bitrev8(map) >> 4; | ||
324 | |||
325 | return map; | ||
326 | } | ||
327 | |||
302 | static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip, | 328 | static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip, |
303 | int where, int size, u32 *val) | 329 | int where, int size, u32 *val) |
304 | { | 330 | { |
@@ -514,10 +540,10 @@ static void rockchip_pcie_set_power_limit(struct rockchip_pcie *rockchip) | |||
514 | static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | 540 | static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) |
515 | { | 541 | { |
516 | struct device *dev = rockchip->dev; | 542 | struct device *dev = rockchip->dev; |
517 | int err; | 543 | int err, i; |
518 | u32 status; | 544 | u32 status; |
519 | 545 | ||
520 | gpiod_set_value(rockchip->ep_gpio, 0); | 546 | gpiod_set_value_cansleep(rockchip->ep_gpio, 0); |
521 | 547 | ||
522 | err = reset_control_assert(rockchip->aclk_rst); | 548 | err = reset_control_assert(rockchip->aclk_rst); |
523 | if (err) { | 549 | if (err) { |
@@ -537,34 +563,36 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | |||
537 | return err; | 563 | return err; |
538 | } | 564 | } |
539 | 565 | ||
540 | err = phy_init(rockchip->phy); | 566 | for (i = 0; i < MAX_LANE_NUM; i++) { |
541 | if (err < 0) { | 567 | err = phy_init(rockchip->phys[i]); |
542 | dev_err(dev, "fail to init phy, err %d\n", err); | 568 | if (err) { |
543 | return err; | 569 | dev_err(dev, "init phy%d err %d\n", i, err); |
570 | goto err_exit_phy; | ||
571 | } | ||
544 | } | 572 | } |
545 | 573 | ||
546 | err = reset_control_assert(rockchip->core_rst); | 574 | err = reset_control_assert(rockchip->core_rst); |
547 | if (err) { | 575 | if (err) { |
548 | dev_err(dev, "assert core_rst err %d\n", err); | 576 | dev_err(dev, "assert core_rst err %d\n", err); |
549 | return err; | 577 | goto err_exit_phy; |
550 | } | 578 | } |
551 | 579 | ||
552 | err = reset_control_assert(rockchip->mgmt_rst); | 580 | err = reset_control_assert(rockchip->mgmt_rst); |
553 | if (err) { | 581 | if (err) { |
554 | dev_err(dev, "assert mgmt_rst err %d\n", err); | 582 | dev_err(dev, "assert mgmt_rst err %d\n", err); |
555 | return err; | 583 | goto err_exit_phy; |
556 | } | 584 | } |
557 | 585 | ||
558 | err = reset_control_assert(rockchip->mgmt_sticky_rst); | 586 | err = reset_control_assert(rockchip->mgmt_sticky_rst); |
559 | if (err) { | 587 | if (err) { |
560 | dev_err(dev, "assert mgmt_sticky_rst err %d\n", err); | 588 | dev_err(dev, "assert mgmt_sticky_rst err %d\n", err); |
561 | return err; | 589 | goto err_exit_phy; |
562 | } | 590 | } |
563 | 591 | ||
564 | err = reset_control_assert(rockchip->pipe_rst); | 592 | err = reset_control_assert(rockchip->pipe_rst); |
565 | if (err) { | 593 | if (err) { |
566 | dev_err(dev, "assert pipe_rst err %d\n", err); | 594 | dev_err(dev, "assert pipe_rst err %d\n", err); |
567 | return err; | 595 | goto err_exit_phy; |
568 | } | 596 | } |
569 | 597 | ||
570 | udelay(10); | 598 | udelay(10); |
@@ -572,19 +600,19 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | |||
572 | err = reset_control_deassert(rockchip->pm_rst); | 600 | err = reset_control_deassert(rockchip->pm_rst); |
573 | if (err) { | 601 | if (err) { |
574 | dev_err(dev, "deassert pm_rst err %d\n", err); | 602 | dev_err(dev, "deassert pm_rst err %d\n", err); |
575 | return err; | 603 | goto err_exit_phy; |
576 | } | 604 | } |
577 | 605 | ||
578 | err = reset_control_deassert(rockchip->aclk_rst); | 606 | err = reset_control_deassert(rockchip->aclk_rst); |
579 | if (err) { | 607 | if (err) { |
580 | dev_err(dev, "deassert aclk_rst err %d\n", err); | 608 | dev_err(dev, "deassert aclk_rst err %d\n", err); |
581 | return err; | 609 | goto err_exit_phy; |
582 | } | 610 | } |
583 | 611 | ||
584 | err = reset_control_deassert(rockchip->pclk_rst); | 612 | err = reset_control_deassert(rockchip->pclk_rst); |
585 | if (err) { | 613 | if (err) { |
586 | dev_err(dev, "deassert pclk_rst err %d\n", err); | 614 | dev_err(dev, "deassert pclk_rst err %d\n", err); |
587 | return err; | 615 | goto err_exit_phy; |
588 | } | 616 | } |
589 | 617 | ||
590 | if (rockchip->link_gen == 2) | 618 | if (rockchip->link_gen == 2) |
@@ -602,10 +630,12 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | |||
602 | PCIE_CLIENT_MODE_RC, | 630 | PCIE_CLIENT_MODE_RC, |
603 | PCIE_CLIENT_CONFIG); | 631 | PCIE_CLIENT_CONFIG); |
604 | 632 | ||
605 | err = phy_power_on(rockchip->phy); | 633 | for (i = 0; i < MAX_LANE_NUM; i++) { |
606 | if (err) { | 634 | err = phy_power_on(rockchip->phys[i]); |
607 | dev_err(dev, "fail to power on phy, err %d\n", err); | 635 | if (err) { |
608 | return err; | 636 | dev_err(dev, "power on phy%d err %d\n", i, err); |
637 | goto err_power_off_phy; | ||
638 | } | ||
609 | } | 639 | } |
610 | 640 | ||
611 | /* | 641 | /* |
@@ -615,25 +645,25 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | |||
615 | err = reset_control_deassert(rockchip->mgmt_sticky_rst); | 645 | err = reset_control_deassert(rockchip->mgmt_sticky_rst); |
616 | if (err) { | 646 | if (err) { |
617 | dev_err(dev, "deassert mgmt_sticky_rst err %d\n", err); | 647 | dev_err(dev, "deassert mgmt_sticky_rst err %d\n", err); |
618 | return err; | 648 | goto err_power_off_phy; |
619 | } | 649 | } |
620 | 650 | ||
621 | err = reset_control_deassert(rockchip->core_rst); | 651 | err = reset_control_deassert(rockchip->core_rst); |
622 | if (err) { | 652 | if (err) { |
623 | dev_err(dev, "deassert core_rst err %d\n", err); | 653 | dev_err(dev, "deassert core_rst err %d\n", err); |
624 | return err; | 654 | goto err_power_off_phy; |
625 | } | 655 | } |
626 | 656 | ||
627 | err = reset_control_deassert(rockchip->mgmt_rst); | 657 | err = reset_control_deassert(rockchip->mgmt_rst); |
628 | if (err) { | 658 | if (err) { |
629 | dev_err(dev, "deassert mgmt_rst err %d\n", err); | 659 | dev_err(dev, "deassert mgmt_rst err %d\n", err); |
630 | return err; | 660 | goto err_power_off_phy; |
631 | } | 661 | } |
632 | 662 | ||
633 | err = reset_control_deassert(rockchip->pipe_rst); | 663 | err = reset_control_deassert(rockchip->pipe_rst); |
634 | if (err) { | 664 | if (err) { |
635 | dev_err(dev, "deassert pipe_rst err %d\n", err); | 665 | dev_err(dev, "deassert pipe_rst err %d\n", err); |
636 | return err; | 666 | goto err_power_off_phy; |
637 | } | 667 | } |
638 | 668 | ||
639 | /* Fix the transmitted FTS count desired to exit from L0s. */ | 669 | /* Fix the transmitted FTS count desired to exit from L0s. */ |
@@ -658,7 +688,7 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | |||
658 | rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE, | 688 | rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE, |
659 | PCIE_CLIENT_CONFIG); | 689 | PCIE_CLIENT_CONFIG); |
660 | 690 | ||
661 | gpiod_set_value(rockchip->ep_gpio, 1); | 691 | gpiod_set_value_cansleep(rockchip->ep_gpio, 1); |
662 | 692 | ||
663 | /* 500ms timeout value should be enough for Gen1/2 training */ | 693 | /* 500ms timeout value should be enough for Gen1/2 training */ |
664 | err = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_BASIC_STATUS1, | 694 | err = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_BASIC_STATUS1, |
@@ -666,7 +696,7 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | |||
666 | 500 * USEC_PER_MSEC); | 696 | 500 * USEC_PER_MSEC); |
667 | if (err) { | 697 | if (err) { |
668 | dev_err(dev, "PCIe link training gen1 timeout!\n"); | 698 | dev_err(dev, "PCIe link training gen1 timeout!\n"); |
669 | return -ETIMEDOUT; | 699 | goto err_power_off_phy; |
670 | } | 700 | } |
671 | 701 | ||
672 | if (rockchip->link_gen == 2) { | 702 | if (rockchip->link_gen == 2) { |
@@ -691,6 +721,15 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | |||
691 | PCIE_CORE_PL_CONF_LANE_SHIFT); | 721 | PCIE_CORE_PL_CONF_LANE_SHIFT); |
692 | dev_dbg(dev, "current link width is x%d\n", status); | 722 | dev_dbg(dev, "current link width is x%d\n", status); |
693 | 723 | ||
724 | /* Power off unused lane(s) */ | ||
725 | rockchip->lanes_map = rockchip_pcie_lane_map(rockchip); | ||
726 | for (i = 0; i < MAX_LANE_NUM; i++) { | ||
727 | if (!(rockchip->lanes_map & BIT(i))) { | ||
728 | dev_dbg(dev, "idling lane %d\n", i); | ||
729 | phy_power_off(rockchip->phys[i]); | ||
730 | } | ||
731 | } | ||
732 | |||
694 | rockchip_pcie_write(rockchip, ROCKCHIP_VENDOR_ID, | 733 | rockchip_pcie_write(rockchip, ROCKCHIP_VENDOR_ID, |
695 | PCIE_CORE_CONFIG_VENDOR); | 734 | PCIE_CORE_CONFIG_VENDOR); |
696 | rockchip_pcie_write(rockchip, | 735 | rockchip_pcie_write(rockchip, |
@@ -715,6 +754,26 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | |||
715 | rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCSR); | 754 | rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCSR); |
716 | 755 | ||
717 | return 0; | 756 | return 0; |
757 | err_power_off_phy: | ||
758 | while (i--) | ||
759 | phy_power_off(rockchip->phys[i]); | ||
760 | i = MAX_LANE_NUM; | ||
761 | err_exit_phy: | ||
762 | while (i--) | ||
763 | phy_exit(rockchip->phys[i]); | ||
764 | return err; | ||
765 | } | ||
766 | |||
767 | static void rockchip_pcie_deinit_phys(struct rockchip_pcie *rockchip) | ||
768 | { | ||
769 | int i; | ||
770 | |||
771 | for (i = 0; i < MAX_LANE_NUM; i++) { | ||
772 | /* inactive lanes are already powered off */ | ||
773 | if (rockchip->lanes_map & BIT(i)) | ||
774 | phy_power_off(rockchip->phys[i]); | ||
775 | phy_exit(rockchip->phys[i]); | ||
776 | } | ||
718 | } | 777 | } |
719 | 778 | ||
720 | static irqreturn_t rockchip_pcie_subsys_irq_handler(int irq, void *arg) | 779 | static irqreturn_t rockchip_pcie_subsys_irq_handler(int irq, void *arg) |
@@ -853,6 +912,91 @@ static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc) | |||
853 | chained_irq_exit(chip, desc); | 912 | chained_irq_exit(chip, desc); |
854 | } | 913 | } |
855 | 914 | ||
915 | static int rockchip_pcie_get_phys(struct rockchip_pcie *rockchip) | ||
916 | { | ||
917 | struct device *dev = rockchip->dev; | ||
918 | struct phy *phy; | ||
919 | char *name; | ||
920 | u32 i; | ||
921 | |||
922 | phy = devm_phy_get(dev, "pcie-phy"); | ||
923 | if (!IS_ERR(phy)) { | ||
924 | rockchip->legacy_phy = true; | ||
925 | rockchip->phys[0] = phy; | ||
926 | dev_warn(dev, "legacy phy model is deprecated!\n"); | ||
927 | return 0; | ||
928 | } | ||
929 | |||
930 | if (PTR_ERR(phy) == -EPROBE_DEFER) | ||
931 | return PTR_ERR(phy); | ||
932 | |||
933 | dev_dbg(dev, "missing legacy phy; search for per-lane PHY\n"); | ||
934 | |||
935 | for (i = 0; i < MAX_LANE_NUM; i++) { | ||
936 | name = kasprintf(GFP_KERNEL, "pcie-phy-%u", i); | ||
937 | if (!name) | ||
938 | return -ENOMEM; | ||
939 | |||
940 | phy = devm_of_phy_get(dev, dev->of_node, name); | ||
941 | kfree(name); | ||
942 | |||
943 | if (IS_ERR(phy)) { | ||
944 | if (PTR_ERR(phy) != -EPROBE_DEFER) | ||
945 | dev_err(dev, "missing phy for lane %d: %ld\n", | ||
946 | i, PTR_ERR(phy)); | ||
947 | return PTR_ERR(phy); | ||
948 | } | ||
949 | |||
950 | rockchip->phys[i] = phy; | ||
951 | } | ||
952 | |||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | static int rockchip_pcie_setup_irq(struct rockchip_pcie *rockchip) | ||
957 | { | ||
958 | int irq, err; | ||
959 | struct device *dev = rockchip->dev; | ||
960 | struct platform_device *pdev = to_platform_device(dev); | ||
961 | |||
962 | irq = platform_get_irq_byname(pdev, "sys"); | ||
963 | if (irq < 0) { | ||
964 | dev_err(dev, "missing sys IRQ resource\n"); | ||
965 | return irq; | ||
966 | } | ||
967 | |||
968 | err = devm_request_irq(dev, irq, rockchip_pcie_subsys_irq_handler, | ||
969 | IRQF_SHARED, "pcie-sys", rockchip); | ||
970 | if (err) { | ||
971 | dev_err(dev, "failed to request PCIe subsystem IRQ\n"); | ||
972 | return err; | ||
973 | } | ||
974 | |||
975 | irq = platform_get_irq_byname(pdev, "legacy"); | ||
976 | if (irq < 0) { | ||
977 | dev_err(dev, "missing legacy IRQ resource\n"); | ||
978 | return irq; | ||
979 | } | ||
980 | |||
981 | irq_set_chained_handler_and_data(irq, | ||
982 | rockchip_pcie_legacy_int_handler, | ||
983 | rockchip); | ||
984 | |||
985 | irq = platform_get_irq_byname(pdev, "client"); | ||
986 | if (irq < 0) { | ||
987 | dev_err(dev, "missing client IRQ resource\n"); | ||
988 | return irq; | ||
989 | } | ||
990 | |||
991 | err = devm_request_irq(dev, irq, rockchip_pcie_client_irq_handler, | ||
992 | IRQF_SHARED, "pcie-client", rockchip); | ||
993 | if (err) { | ||
994 | dev_err(dev, "failed to request PCIe client IRQ\n"); | ||
995 | return err; | ||
996 | } | ||
997 | |||
998 | return 0; | ||
999 | } | ||
856 | 1000 | ||
857 | /** | 1001 | /** |
858 | * rockchip_pcie_parse_dt - Parse Device Tree | 1002 | * rockchip_pcie_parse_dt - Parse Device Tree |
@@ -866,7 +1010,6 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) | |||
866 | struct platform_device *pdev = to_platform_device(dev); | 1010 | struct platform_device *pdev = to_platform_device(dev); |
867 | struct device_node *node = dev->of_node; | 1011 | struct device_node *node = dev->of_node; |
868 | struct resource *regs; | 1012 | struct resource *regs; |
869 | int irq; | ||
870 | int err; | 1013 | int err; |
871 | 1014 | ||
872 | regs = platform_get_resource_byname(pdev, | 1015 | regs = platform_get_resource_byname(pdev, |
@@ -883,12 +1026,9 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) | |||
883 | if (IS_ERR(rockchip->apb_base)) | 1026 | if (IS_ERR(rockchip->apb_base)) |
884 | return PTR_ERR(rockchip->apb_base); | 1027 | return PTR_ERR(rockchip->apb_base); |
885 | 1028 | ||
886 | rockchip->phy = devm_phy_get(dev, "pcie-phy"); | 1029 | err = rockchip_pcie_get_phys(rockchip); |
887 | if (IS_ERR(rockchip->phy)) { | 1030 | if (err) |
888 | if (PTR_ERR(rockchip->phy) != -EPROBE_DEFER) | 1031 | return err; |
889 | dev_err(dev, "missing phy\n"); | ||
890 | return PTR_ERR(rockchip->phy); | ||
891 | } | ||
892 | 1032 | ||
893 | rockchip->lanes = 1; | 1033 | rockchip->lanes = 1; |
894 | err = of_property_read_u32(node, "num-lanes", &rockchip->lanes); | 1034 | err = of_property_read_u32(node, "num-lanes", &rockchip->lanes); |
@@ -903,49 +1043,50 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) | |||
903 | if (rockchip->link_gen < 0 || rockchip->link_gen > 2) | 1043 | if (rockchip->link_gen < 0 || rockchip->link_gen > 2) |
904 | rockchip->link_gen = 2; | 1044 | rockchip->link_gen = 2; |
905 | 1045 | ||
906 | rockchip->core_rst = devm_reset_control_get(dev, "core"); | 1046 | rockchip->core_rst = devm_reset_control_get_exclusive(dev, "core"); |
907 | if (IS_ERR(rockchip->core_rst)) { | 1047 | if (IS_ERR(rockchip->core_rst)) { |
908 | if (PTR_ERR(rockchip->core_rst) != -EPROBE_DEFER) | 1048 | if (PTR_ERR(rockchip->core_rst) != -EPROBE_DEFER) |
909 | dev_err(dev, "missing core reset property in node\n"); | 1049 | dev_err(dev, "missing core reset property in node\n"); |
910 | return PTR_ERR(rockchip->core_rst); | 1050 | return PTR_ERR(rockchip->core_rst); |
911 | } | 1051 | } |
912 | 1052 | ||
913 | rockchip->mgmt_rst = devm_reset_control_get(dev, "mgmt"); | 1053 | rockchip->mgmt_rst = devm_reset_control_get_exclusive(dev, "mgmt"); |
914 | if (IS_ERR(rockchip->mgmt_rst)) { | 1054 | if (IS_ERR(rockchip->mgmt_rst)) { |
915 | if (PTR_ERR(rockchip->mgmt_rst) != -EPROBE_DEFER) | 1055 | if (PTR_ERR(rockchip->mgmt_rst) != -EPROBE_DEFER) |
916 | dev_err(dev, "missing mgmt reset property in node\n"); | 1056 | dev_err(dev, "missing mgmt reset property in node\n"); |
917 | return PTR_ERR(rockchip->mgmt_rst); | 1057 | return PTR_ERR(rockchip->mgmt_rst); |
918 | } | 1058 | } |
919 | 1059 | ||
920 | rockchip->mgmt_sticky_rst = devm_reset_control_get(dev, "mgmt-sticky"); | 1060 | rockchip->mgmt_sticky_rst = devm_reset_control_get_exclusive(dev, |
1061 | "mgmt-sticky"); | ||
921 | if (IS_ERR(rockchip->mgmt_sticky_rst)) { | 1062 | if (IS_ERR(rockchip->mgmt_sticky_rst)) { |
922 | if (PTR_ERR(rockchip->mgmt_sticky_rst) != -EPROBE_DEFER) | 1063 | if (PTR_ERR(rockchip->mgmt_sticky_rst) != -EPROBE_DEFER) |
923 | dev_err(dev, "missing mgmt-sticky reset property in node\n"); | 1064 | dev_err(dev, "missing mgmt-sticky reset property in node\n"); |
924 | return PTR_ERR(rockchip->mgmt_sticky_rst); | 1065 | return PTR_ERR(rockchip->mgmt_sticky_rst); |
925 | } | 1066 | } |
926 | 1067 | ||
927 | rockchip->pipe_rst = devm_reset_control_get(dev, "pipe"); | 1068 | rockchip->pipe_rst = devm_reset_control_get_exclusive(dev, "pipe"); |
928 | if (IS_ERR(rockchip->pipe_rst)) { | 1069 | if (IS_ERR(rockchip->pipe_rst)) { |
929 | if (PTR_ERR(rockchip->pipe_rst) != -EPROBE_DEFER) | 1070 | if (PTR_ERR(rockchip->pipe_rst) != -EPROBE_DEFER) |
930 | dev_err(dev, "missing pipe reset property in node\n"); | 1071 | dev_err(dev, "missing pipe reset property in node\n"); |
931 | return PTR_ERR(rockchip->pipe_rst); | 1072 | return PTR_ERR(rockchip->pipe_rst); |
932 | } | 1073 | } |
933 | 1074 | ||
934 | rockchip->pm_rst = devm_reset_control_get(dev, "pm"); | 1075 | rockchip->pm_rst = devm_reset_control_get_exclusive(dev, "pm"); |
935 | if (IS_ERR(rockchip->pm_rst)) { | 1076 | if (IS_ERR(rockchip->pm_rst)) { |
936 | if (PTR_ERR(rockchip->pm_rst) != -EPROBE_DEFER) | 1077 | if (PTR_ERR(rockchip->pm_rst) != -EPROBE_DEFER) |
937 | dev_err(dev, "missing pm reset property in node\n"); | 1078 | dev_err(dev, "missing pm reset property in node\n"); |
938 | return PTR_ERR(rockchip->pm_rst); | 1079 | return PTR_ERR(rockchip->pm_rst); |
939 | } | 1080 | } |
940 | 1081 | ||
941 | rockchip->pclk_rst = devm_reset_control_get(dev, "pclk"); | 1082 | rockchip->pclk_rst = devm_reset_control_get_exclusive(dev, "pclk"); |
942 | if (IS_ERR(rockchip->pclk_rst)) { | 1083 | if (IS_ERR(rockchip->pclk_rst)) { |
943 | if (PTR_ERR(rockchip->pclk_rst) != -EPROBE_DEFER) | 1084 | if (PTR_ERR(rockchip->pclk_rst) != -EPROBE_DEFER) |
944 | dev_err(dev, "missing pclk reset property in node\n"); | 1085 | dev_err(dev, "missing pclk reset property in node\n"); |
945 | return PTR_ERR(rockchip->pclk_rst); | 1086 | return PTR_ERR(rockchip->pclk_rst); |
946 | } | 1087 | } |
947 | 1088 | ||
948 | rockchip->aclk_rst = devm_reset_control_get(dev, "aclk"); | 1089 | rockchip->aclk_rst = devm_reset_control_get_exclusive(dev, "aclk"); |
949 | if (IS_ERR(rockchip->aclk_rst)) { | 1090 | if (IS_ERR(rockchip->aclk_rst)) { |
950 | if (PTR_ERR(rockchip->aclk_rst) != -EPROBE_DEFER) | 1091 | if (PTR_ERR(rockchip->aclk_rst) != -EPROBE_DEFER) |
951 | dev_err(dev, "missing aclk reset property in node\n"); | 1092 | dev_err(dev, "missing aclk reset property in node\n"); |
@@ -982,40 +1123,15 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) | |||
982 | return PTR_ERR(rockchip->clk_pcie_pm); | 1123 | return PTR_ERR(rockchip->clk_pcie_pm); |
983 | } | 1124 | } |
984 | 1125 | ||
985 | irq = platform_get_irq_byname(pdev, "sys"); | 1126 | err = rockchip_pcie_setup_irq(rockchip); |
986 | if (irq < 0) { | 1127 | if (err) |
987 | dev_err(dev, "missing sys IRQ resource\n"); | ||
988 | return -EINVAL; | ||
989 | } | ||
990 | |||
991 | err = devm_request_irq(dev, irq, rockchip_pcie_subsys_irq_handler, | ||
992 | IRQF_SHARED, "pcie-sys", rockchip); | ||
993 | if (err) { | ||
994 | dev_err(dev, "failed to request PCIe subsystem IRQ\n"); | ||
995 | return err; | 1128 | return err; |
996 | } | ||
997 | |||
998 | irq = platform_get_irq_byname(pdev, "legacy"); | ||
999 | if (irq < 0) { | ||
1000 | dev_err(dev, "missing legacy IRQ resource\n"); | ||
1001 | return -EINVAL; | ||
1002 | } | ||
1003 | |||
1004 | irq_set_chained_handler_and_data(irq, | ||
1005 | rockchip_pcie_legacy_int_handler, | ||
1006 | rockchip); | ||
1007 | |||
1008 | irq = platform_get_irq_byname(pdev, "client"); | ||
1009 | if (irq < 0) { | ||
1010 | dev_err(dev, "missing client IRQ resource\n"); | ||
1011 | return -EINVAL; | ||
1012 | } | ||
1013 | 1129 | ||
1014 | err = devm_request_irq(dev, irq, rockchip_pcie_client_irq_handler, | 1130 | rockchip->vpcie12v = devm_regulator_get_optional(dev, "vpcie12v"); |
1015 | IRQF_SHARED, "pcie-client", rockchip); | 1131 | if (IS_ERR(rockchip->vpcie12v)) { |
1016 | if (err) { | 1132 | if (PTR_ERR(rockchip->vpcie12v) == -EPROBE_DEFER) |
1017 | dev_err(dev, "failed to request PCIe client IRQ\n"); | 1133 | return -EPROBE_DEFER; |
1018 | return err; | 1134 | dev_info(dev, "no vpcie12v regulator found\n"); |
1019 | } | 1135 | } |
1020 | 1136 | ||
1021 | rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3"); | 1137 | rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3"); |
@@ -1047,11 +1163,19 @@ static int rockchip_pcie_set_vpcie(struct rockchip_pcie *rockchip) | |||
1047 | struct device *dev = rockchip->dev; | 1163 | struct device *dev = rockchip->dev; |
1048 | int err; | 1164 | int err; |
1049 | 1165 | ||
1166 | if (!IS_ERR(rockchip->vpcie12v)) { | ||
1167 | err = regulator_enable(rockchip->vpcie12v); | ||
1168 | if (err) { | ||
1169 | dev_err(dev, "fail to enable vpcie12v regulator\n"); | ||
1170 | goto err_out; | ||
1171 | } | ||
1172 | } | ||
1173 | |||
1050 | if (!IS_ERR(rockchip->vpcie3v3)) { | 1174 | if (!IS_ERR(rockchip->vpcie3v3)) { |
1051 | err = regulator_enable(rockchip->vpcie3v3); | 1175 | err = regulator_enable(rockchip->vpcie3v3); |
1052 | if (err) { | 1176 | if (err) { |
1053 | dev_err(dev, "fail to enable vpcie3v3 regulator\n"); | 1177 | dev_err(dev, "fail to enable vpcie3v3 regulator\n"); |
1054 | goto err_out; | 1178 | goto err_disable_12v; |
1055 | } | 1179 | } |
1056 | } | 1180 | } |
1057 | 1181 | ||
@@ -1079,6 +1203,9 @@ err_disable_1v8: | |||
1079 | err_disable_3v3: | 1203 | err_disable_3v3: |
1080 | if (!IS_ERR(rockchip->vpcie3v3)) | 1204 | if (!IS_ERR(rockchip->vpcie3v3)) |
1081 | regulator_disable(rockchip->vpcie3v3); | 1205 | regulator_disable(rockchip->vpcie3v3); |
1206 | err_disable_12v: | ||
1207 | if (!IS_ERR(rockchip->vpcie12v)) | ||
1208 | regulator_disable(rockchip->vpcie12v); | ||
1082 | err_out: | 1209 | err_out: |
1083 | return err; | 1210 | return err; |
1084 | } | 1211 | } |
@@ -1116,7 +1243,7 @@ static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip) | |||
1116 | return -EINVAL; | 1243 | return -EINVAL; |
1117 | } | 1244 | } |
1118 | 1245 | ||
1119 | rockchip->irq_domain = irq_domain_add_linear(intc, 4, | 1246 | rockchip->irq_domain = irq_domain_add_linear(intc, PCI_NUM_INTX, |
1120 | &intx_domain_ops, rockchip); | 1247 | &intx_domain_ops, rockchip); |
1121 | if (!rockchip->irq_domain) { | 1248 | if (!rockchip->irq_domain) { |
1122 | dev_err(dev, "failed to get a INTx IRQ domain\n"); | 1249 | dev_err(dev, "failed to get a INTx IRQ domain\n"); |
@@ -1270,6 +1397,56 @@ static int rockchip_pcie_wait_l2(struct rockchip_pcie *rockchip) | |||
1270 | return 0; | 1397 | return 0; |
1271 | } | 1398 | } |
1272 | 1399 | ||
1400 | static int rockchip_pcie_enable_clocks(struct rockchip_pcie *rockchip) | ||
1401 | { | ||
1402 | struct device *dev = rockchip->dev; | ||
1403 | int err; | ||
1404 | |||
1405 | err = clk_prepare_enable(rockchip->aclk_pcie); | ||
1406 | if (err) { | ||
1407 | dev_err(dev, "unable to enable aclk_pcie clock\n"); | ||
1408 | return err; | ||
1409 | } | ||
1410 | |||
1411 | err = clk_prepare_enable(rockchip->aclk_perf_pcie); | ||
1412 | if (err) { | ||
1413 | dev_err(dev, "unable to enable aclk_perf_pcie clock\n"); | ||
1414 | goto err_aclk_perf_pcie; | ||
1415 | } | ||
1416 | |||
1417 | err = clk_prepare_enable(rockchip->hclk_pcie); | ||
1418 | if (err) { | ||
1419 | dev_err(dev, "unable to enable hclk_pcie clock\n"); | ||
1420 | goto err_hclk_pcie; | ||
1421 | } | ||
1422 | |||
1423 | err = clk_prepare_enable(rockchip->clk_pcie_pm); | ||
1424 | if (err) { | ||
1425 | dev_err(dev, "unable to enable clk_pcie_pm clock\n"); | ||
1426 | goto err_clk_pcie_pm; | ||
1427 | } | ||
1428 | |||
1429 | return 0; | ||
1430 | |||
1431 | err_clk_pcie_pm: | ||
1432 | clk_disable_unprepare(rockchip->hclk_pcie); | ||
1433 | err_hclk_pcie: | ||
1434 | clk_disable_unprepare(rockchip->aclk_perf_pcie); | ||
1435 | err_aclk_perf_pcie: | ||
1436 | clk_disable_unprepare(rockchip->aclk_pcie); | ||
1437 | return err; | ||
1438 | } | ||
1439 | |||
1440 | static void rockchip_pcie_disable_clocks(void *data) | ||
1441 | { | ||
1442 | struct rockchip_pcie *rockchip = data; | ||
1443 | |||
1444 | clk_disable_unprepare(rockchip->clk_pcie_pm); | ||
1445 | clk_disable_unprepare(rockchip->hclk_pcie); | ||
1446 | clk_disable_unprepare(rockchip->aclk_perf_pcie); | ||
1447 | clk_disable_unprepare(rockchip->aclk_pcie); | ||
1448 | } | ||
1449 | |||
1273 | static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev) | 1450 | static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev) |
1274 | { | 1451 | { |
1275 | struct rockchip_pcie *rockchip = dev_get_drvdata(dev); | 1452 | struct rockchip_pcie *rockchip = dev_get_drvdata(dev); |
@@ -1286,13 +1463,9 @@ static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev) | |||
1286 | return ret; | 1463 | return ret; |
1287 | } | 1464 | } |
1288 | 1465 | ||
1289 | phy_power_off(rockchip->phy); | 1466 | rockchip_pcie_deinit_phys(rockchip); |
1290 | phy_exit(rockchip->phy); | ||
1291 | 1467 | ||
1292 | clk_disable_unprepare(rockchip->clk_pcie_pm); | 1468 | rockchip_pcie_disable_clocks(rockchip); |
1293 | clk_disable_unprepare(rockchip->hclk_pcie); | ||
1294 | clk_disable_unprepare(rockchip->aclk_perf_pcie); | ||
1295 | clk_disable_unprepare(rockchip->aclk_pcie); | ||
1296 | 1469 | ||
1297 | if (!IS_ERR(rockchip->vpcie0v9)) | 1470 | if (!IS_ERR(rockchip->vpcie0v9)) |
1298 | regulator_disable(rockchip->vpcie0v9); | 1471 | regulator_disable(rockchip->vpcie0v9); |
@@ -1313,21 +1486,9 @@ static int __maybe_unused rockchip_pcie_resume_noirq(struct device *dev) | |||
1313 | } | 1486 | } |
1314 | } | 1487 | } |
1315 | 1488 | ||
1316 | err = clk_prepare_enable(rockchip->clk_pcie_pm); | 1489 | err = rockchip_pcie_enable_clocks(rockchip); |
1317 | if (err) | 1490 | if (err) |
1318 | goto err_pcie_pm; | 1491 | goto err_disable_0v9; |
1319 | |||
1320 | err = clk_prepare_enable(rockchip->hclk_pcie); | ||
1321 | if (err) | ||
1322 | goto err_hclk_pcie; | ||
1323 | |||
1324 | err = clk_prepare_enable(rockchip->aclk_perf_pcie); | ||
1325 | if (err) | ||
1326 | goto err_aclk_perf_pcie; | ||
1327 | |||
1328 | err = clk_prepare_enable(rockchip->aclk_pcie); | ||
1329 | if (err) | ||
1330 | goto err_aclk_pcie; | ||
1331 | 1492 | ||
1332 | err = rockchip_pcie_init_port(rockchip); | 1493 | err = rockchip_pcie_init_port(rockchip); |
1333 | if (err) | 1494 | if (err) |
@@ -1335,7 +1496,7 @@ static int __maybe_unused rockchip_pcie_resume_noirq(struct device *dev) | |||
1335 | 1496 | ||
1336 | err = rockchip_pcie_cfg_atu(rockchip); | 1497 | err = rockchip_pcie_cfg_atu(rockchip); |
1337 | if (err) | 1498 | if (err) |
1338 | goto err_pcie_resume; | 1499 | goto err_err_deinit_port; |
1339 | 1500 | ||
1340 | /* Need this to enter L1 again */ | 1501 | /* Need this to enter L1 again */ |
1341 | rockchip_pcie_update_txcredit_mui(rockchip); | 1502 | rockchip_pcie_update_txcredit_mui(rockchip); |
@@ -1343,15 +1504,13 @@ static int __maybe_unused rockchip_pcie_resume_noirq(struct device *dev) | |||
1343 | 1504 | ||
1344 | return 0; | 1505 | return 0; |
1345 | 1506 | ||
1507 | err_err_deinit_port: | ||
1508 | rockchip_pcie_deinit_phys(rockchip); | ||
1346 | err_pcie_resume: | 1509 | err_pcie_resume: |
1347 | clk_disable_unprepare(rockchip->aclk_pcie); | 1510 | rockchip_pcie_disable_clocks(rockchip); |
1348 | err_aclk_pcie: | 1511 | err_disable_0v9: |
1349 | clk_disable_unprepare(rockchip->aclk_perf_pcie); | 1512 | if (!IS_ERR(rockchip->vpcie0v9)) |
1350 | err_aclk_perf_pcie: | 1513 | regulator_disable(rockchip->vpcie0v9); |
1351 | clk_disable_unprepare(rockchip->hclk_pcie); | ||
1352 | err_hclk_pcie: | ||
1353 | clk_disable_unprepare(rockchip->clk_pcie_pm); | ||
1354 | err_pcie_pm: | ||
1355 | return err; | 1514 | return err; |
1356 | } | 1515 | } |
1357 | 1516 | ||
@@ -1385,29 +1544,9 @@ static int rockchip_pcie_probe(struct platform_device *pdev) | |||
1385 | if (err) | 1544 | if (err) |
1386 | return err; | 1545 | return err; |
1387 | 1546 | ||
1388 | err = clk_prepare_enable(rockchip->aclk_pcie); | 1547 | err = rockchip_pcie_enable_clocks(rockchip); |
1389 | if (err) { | 1548 | if (err) |
1390 | dev_err(dev, "unable to enable aclk_pcie clock\n"); | 1549 | return err; |
1391 | goto err_aclk_pcie; | ||
1392 | } | ||
1393 | |||
1394 | err = clk_prepare_enable(rockchip->aclk_perf_pcie); | ||
1395 | if (err) { | ||
1396 | dev_err(dev, "unable to enable aclk_perf_pcie clock\n"); | ||
1397 | goto err_aclk_perf_pcie; | ||
1398 | } | ||
1399 | |||
1400 | err = clk_prepare_enable(rockchip->hclk_pcie); | ||
1401 | if (err) { | ||
1402 | dev_err(dev, "unable to enable hclk_pcie clock\n"); | ||
1403 | goto err_hclk_pcie; | ||
1404 | } | ||
1405 | |||
1406 | err = clk_prepare_enable(rockchip->clk_pcie_pm); | ||
1407 | if (err) { | ||
1408 | dev_err(dev, "unable to enable hclk_pcie clock\n"); | ||
1409 | goto err_pcie_pm; | ||
1410 | } | ||
1411 | 1550 | ||
1412 | err = rockchip_pcie_set_vpcie(rockchip); | 1551 | err = rockchip_pcie_set_vpcie(rockchip); |
1413 | if (err) { | 1552 | if (err) { |
@@ -1423,12 +1562,12 @@ static int rockchip_pcie_probe(struct platform_device *pdev) | |||
1423 | 1562 | ||
1424 | err = rockchip_pcie_init_irq_domain(rockchip); | 1563 | err = rockchip_pcie_init_irq_domain(rockchip); |
1425 | if (err < 0) | 1564 | if (err < 0) |
1426 | goto err_vpcie; | 1565 | goto err_deinit_port; |
1427 | 1566 | ||
1428 | err = of_pci_get_host_bridge_resources(dev->of_node, 0, 0xff, | 1567 | err = of_pci_get_host_bridge_resources(dev->of_node, 0, 0xff, |
1429 | &res, &io_base); | 1568 | &res, &io_base); |
1430 | if (err) | 1569 | if (err) |
1431 | goto err_vpcie; | 1570 | goto err_remove_irq_domain; |
1432 | 1571 | ||
1433 | err = devm_request_pci_bus_resources(dev, &res); | 1572 | err = devm_request_pci_bus_resources(dev, &res); |
1434 | if (err) | 1573 | if (err) |
@@ -1466,12 +1605,12 @@ static int rockchip_pcie_probe(struct platform_device *pdev) | |||
1466 | 1605 | ||
1467 | err = rockchip_pcie_cfg_atu(rockchip); | 1606 | err = rockchip_pcie_cfg_atu(rockchip); |
1468 | if (err) | 1607 | if (err) |
1469 | goto err_free_res; | 1608 | goto err_unmap_iospace; |
1470 | 1609 | ||
1471 | rockchip->msg_region = devm_ioremap(dev, rockchip->msg_bus_addr, SZ_1M); | 1610 | rockchip->msg_region = devm_ioremap(dev, rockchip->msg_bus_addr, SZ_1M); |
1472 | if (!rockchip->msg_region) { | 1611 | if (!rockchip->msg_region) { |
1473 | err = -ENOMEM; | 1612 | err = -ENOMEM; |
1474 | goto err_free_res; | 1613 | goto err_unmap_iospace; |
1475 | } | 1614 | } |
1476 | 1615 | ||
1477 | list_splice_init(&res, &bridge->windows); | 1616 | list_splice_init(&res, &bridge->windows); |
@@ -1484,7 +1623,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev) | |||
1484 | 1623 | ||
1485 | err = pci_scan_root_bus_bridge(bridge); | 1624 | err = pci_scan_root_bus_bridge(bridge); |
1486 | if (err < 0) | 1625 | if (err < 0) |
1487 | goto err_free_res; | 1626 | goto err_unmap_iospace; |
1488 | 1627 | ||
1489 | bus = bridge->bus; | 1628 | bus = bridge->bus; |
1490 | 1629 | ||
@@ -1498,9 +1637,17 @@ static int rockchip_pcie_probe(struct platform_device *pdev) | |||
1498 | pci_bus_add_devices(bus); | 1637 | pci_bus_add_devices(bus); |
1499 | return 0; | 1638 | return 0; |
1500 | 1639 | ||
1640 | err_unmap_iospace: | ||
1641 | pci_unmap_iospace(rockchip->io); | ||
1501 | err_free_res: | 1642 | err_free_res: |
1502 | pci_free_resource_list(&res); | 1643 | pci_free_resource_list(&res); |
1644 | err_remove_irq_domain: | ||
1645 | irq_domain_remove(rockchip->irq_domain); | ||
1646 | err_deinit_port: | ||
1647 | rockchip_pcie_deinit_phys(rockchip); | ||
1503 | err_vpcie: | 1648 | err_vpcie: |
1649 | if (!IS_ERR(rockchip->vpcie12v)) | ||
1650 | regulator_disable(rockchip->vpcie12v); | ||
1504 | if (!IS_ERR(rockchip->vpcie3v3)) | 1651 | if (!IS_ERR(rockchip->vpcie3v3)) |
1505 | regulator_disable(rockchip->vpcie3v3); | 1652 | regulator_disable(rockchip->vpcie3v3); |
1506 | if (!IS_ERR(rockchip->vpcie1v8)) | 1653 | if (!IS_ERR(rockchip->vpcie1v8)) |
@@ -1508,14 +1655,7 @@ err_vpcie: | |||
1508 | if (!IS_ERR(rockchip->vpcie0v9)) | 1655 | if (!IS_ERR(rockchip->vpcie0v9)) |
1509 | regulator_disable(rockchip->vpcie0v9); | 1656 | regulator_disable(rockchip->vpcie0v9); |
1510 | err_set_vpcie: | 1657 | err_set_vpcie: |
1511 | clk_disable_unprepare(rockchip->clk_pcie_pm); | 1658 | rockchip_pcie_disable_clocks(rockchip); |
1512 | err_pcie_pm: | ||
1513 | clk_disable_unprepare(rockchip->hclk_pcie); | ||
1514 | err_hclk_pcie: | ||
1515 | clk_disable_unprepare(rockchip->aclk_perf_pcie); | ||
1516 | err_aclk_perf_pcie: | ||
1517 | clk_disable_unprepare(rockchip->aclk_pcie); | ||
1518 | err_aclk_pcie: | ||
1519 | return err; | 1659 | return err; |
1520 | } | 1660 | } |
1521 | 1661 | ||
@@ -1529,14 +1669,12 @@ static int rockchip_pcie_remove(struct platform_device *pdev) | |||
1529 | pci_unmap_iospace(rockchip->io); | 1669 | pci_unmap_iospace(rockchip->io); |
1530 | irq_domain_remove(rockchip->irq_domain); | 1670 | irq_domain_remove(rockchip->irq_domain); |
1531 | 1671 | ||
1532 | phy_power_off(rockchip->phy); | 1672 | rockchip_pcie_deinit_phys(rockchip); |
1533 | phy_exit(rockchip->phy); | ||
1534 | 1673 | ||
1535 | clk_disable_unprepare(rockchip->clk_pcie_pm); | 1674 | rockchip_pcie_disable_clocks(rockchip); |
1536 | clk_disable_unprepare(rockchip->hclk_pcie); | ||
1537 | clk_disable_unprepare(rockchip->aclk_perf_pcie); | ||
1538 | clk_disable_unprepare(rockchip->aclk_pcie); | ||
1539 | 1675 | ||
1676 | if (!IS_ERR(rockchip->vpcie12v)) | ||
1677 | regulator_disable(rockchip->vpcie12v); | ||
1540 | if (!IS_ERR(rockchip->vpcie3v3)) | 1678 | if (!IS_ERR(rockchip->vpcie3v3)) |
1541 | regulator_disable(rockchip->vpcie3v3); | 1679 | regulator_disable(rockchip->vpcie3v3); |
1542 | if (!IS_ERR(rockchip->vpcie1v8)) | 1680 | if (!IS_ERR(rockchip->vpcie1v8)) |
diff --git a/drivers/phy/rockchip/phy-rockchip-pcie.c b/drivers/phy/rockchip/phy-rockchip-pcie.c index 6904633cad68..7cbdde029c0a 100644 --- a/drivers/phy/rockchip/phy-rockchip-pcie.c +++ b/drivers/phy/rockchip/phy-rockchip-pcie.c | |||
@@ -73,10 +73,38 @@ struct rockchip_pcie_data { | |||
73 | struct rockchip_pcie_phy { | 73 | struct rockchip_pcie_phy { |
74 | struct rockchip_pcie_data *phy_data; | 74 | struct rockchip_pcie_data *phy_data; |
75 | struct regmap *reg_base; | 75 | struct regmap *reg_base; |
76 | struct phy_pcie_instance { | ||
77 | struct phy *phy; | ||
78 | u32 index; | ||
79 | } phys[PHY_MAX_LANE_NUM]; | ||
80 | struct mutex pcie_mutex; | ||
76 | struct reset_control *phy_rst; | 81 | struct reset_control *phy_rst; |
77 | struct clk *clk_pciephy_ref; | 82 | struct clk *clk_pciephy_ref; |
83 | int pwr_cnt; | ||
84 | int init_cnt; | ||
78 | }; | 85 | }; |
79 | 86 | ||
87 | static struct rockchip_pcie_phy *to_pcie_phy(struct phy_pcie_instance *inst) | ||
88 | { | ||
89 | return container_of(inst, struct rockchip_pcie_phy, | ||
90 | phys[inst->index]); | ||
91 | } | ||
92 | |||
93 | static struct phy *rockchip_pcie_phy_of_xlate(struct device *dev, | ||
94 | struct of_phandle_args *args) | ||
95 | { | ||
96 | struct rockchip_pcie_phy *rk_phy = dev_get_drvdata(dev); | ||
97 | |||
98 | if (args->args_count == 0) | ||
99 | return rk_phy->phys[0].phy; | ||
100 | |||
101 | if (WARN_ON(args->args[0] >= PHY_MAX_LANE_NUM)) | ||
102 | return ERR_PTR(-ENODEV); | ||
103 | |||
104 | return rk_phy->phys[args->args[0]].phy; | ||
105 | } | ||
106 | |||
107 | |||
80 | static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy, | 108 | static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy, |
81 | u32 addr, u32 data) | 109 | u32 addr, u32 data) |
82 | { | 110 | { |
@@ -116,29 +144,59 @@ static inline u32 phy_rd_cfg(struct rockchip_pcie_phy *rk_phy, | |||
116 | 144 | ||
117 | static int rockchip_pcie_phy_power_off(struct phy *phy) | 145 | static int rockchip_pcie_phy_power_off(struct phy *phy) |
118 | { | 146 | { |
119 | struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); | 147 | struct phy_pcie_instance *inst = phy_get_drvdata(phy); |
148 | struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst); | ||
120 | int err = 0; | 149 | int err = 0; |
121 | 150 | ||
151 | mutex_lock(&rk_phy->pcie_mutex); | ||
152 | |||
153 | regmap_write(rk_phy->reg_base, | ||
154 | rk_phy->phy_data->pcie_laneoff, | ||
155 | HIWORD_UPDATE(PHY_LANE_IDLE_OFF, | ||
156 | PHY_LANE_IDLE_MASK, | ||
157 | PHY_LANE_IDLE_A_SHIFT + inst->index)); | ||
158 | |||
159 | if (--rk_phy->pwr_cnt) | ||
160 | goto err_out; | ||
161 | |||
122 | err = reset_control_assert(rk_phy->phy_rst); | 162 | err = reset_control_assert(rk_phy->phy_rst); |
123 | if (err) { | 163 | if (err) { |
124 | dev_err(&phy->dev, "assert phy_rst err %d\n", err); | 164 | dev_err(&phy->dev, "assert phy_rst err %d\n", err); |
125 | return err; | 165 | goto err_restore; |
126 | } | 166 | } |
127 | 167 | ||
168 | err_out: | ||
169 | mutex_unlock(&rk_phy->pcie_mutex); | ||
128 | return 0; | 170 | return 0; |
171 | |||
172 | err_restore: | ||
173 | rk_phy->pwr_cnt++; | ||
174 | regmap_write(rk_phy->reg_base, | ||
175 | rk_phy->phy_data->pcie_laneoff, | ||
176 | HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, | ||
177 | PHY_LANE_IDLE_MASK, | ||
178 | PHY_LANE_IDLE_A_SHIFT + inst->index)); | ||
179 | mutex_unlock(&rk_phy->pcie_mutex); | ||
180 | return err; | ||
129 | } | 181 | } |
130 | 182 | ||
131 | static int rockchip_pcie_phy_power_on(struct phy *phy) | 183 | static int rockchip_pcie_phy_power_on(struct phy *phy) |
132 | { | 184 | { |
133 | struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); | 185 | struct phy_pcie_instance *inst = phy_get_drvdata(phy); |
186 | struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst); | ||
134 | int err = 0; | 187 | int err = 0; |
135 | u32 status; | 188 | u32 status; |
136 | unsigned long timeout; | 189 | unsigned long timeout; |
137 | 190 | ||
191 | mutex_lock(&rk_phy->pcie_mutex); | ||
192 | |||
193 | if (rk_phy->pwr_cnt++) | ||
194 | goto err_out; | ||
195 | |||
138 | err = reset_control_deassert(rk_phy->phy_rst); | 196 | err = reset_control_deassert(rk_phy->phy_rst); |
139 | if (err) { | 197 | if (err) { |
140 | dev_err(&phy->dev, "deassert phy_rst err %d\n", err); | 198 | dev_err(&phy->dev, "deassert phy_rst err %d\n", err); |
141 | return err; | 199 | goto err_pwr_cnt; |
142 | } | 200 | } |
143 | 201 | ||
144 | regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, | 202 | regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, |
@@ -146,6 +204,12 @@ static int rockchip_pcie_phy_power_on(struct phy *phy) | |||
146 | PHY_CFG_ADDR_MASK, | 204 | PHY_CFG_ADDR_MASK, |
147 | PHY_CFG_ADDR_SHIFT)); | 205 | PHY_CFG_ADDR_SHIFT)); |
148 | 206 | ||
207 | regmap_write(rk_phy->reg_base, | ||
208 | rk_phy->phy_data->pcie_laneoff, | ||
209 | HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, | ||
210 | PHY_LANE_IDLE_MASK, | ||
211 | PHY_LANE_IDLE_A_SHIFT + inst->index)); | ||
212 | |||
149 | /* | 213 | /* |
150 | * No documented timeout value for phy operation below, | 214 | * No documented timeout value for phy operation below, |
151 | * so we make it large enough here. And we use loop-break | 215 | * so we make it large enough here. And we use loop-break |
@@ -214,18 +278,29 @@ static int rockchip_pcie_phy_power_on(struct phy *phy) | |||
214 | goto err_pll_lock; | 278 | goto err_pll_lock; |
215 | } | 279 | } |
216 | 280 | ||
281 | err_out: | ||
282 | mutex_unlock(&rk_phy->pcie_mutex); | ||
217 | return 0; | 283 | return 0; |
218 | 284 | ||
219 | err_pll_lock: | 285 | err_pll_lock: |
220 | reset_control_assert(rk_phy->phy_rst); | 286 | reset_control_assert(rk_phy->phy_rst); |
287 | err_pwr_cnt: | ||
288 | rk_phy->pwr_cnt--; | ||
289 | mutex_unlock(&rk_phy->pcie_mutex); | ||
221 | return err; | 290 | return err; |
222 | } | 291 | } |
223 | 292 | ||
224 | static int rockchip_pcie_phy_init(struct phy *phy) | 293 | static int rockchip_pcie_phy_init(struct phy *phy) |
225 | { | 294 | { |
226 | struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); | 295 | struct phy_pcie_instance *inst = phy_get_drvdata(phy); |
296 | struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst); | ||
227 | int err = 0; | 297 | int err = 0; |
228 | 298 | ||
299 | mutex_lock(&rk_phy->pcie_mutex); | ||
300 | |||
301 | if (rk_phy->init_cnt++) | ||
302 | goto err_out; | ||
303 | |||
229 | err = clk_prepare_enable(rk_phy->clk_pciephy_ref); | 304 | err = clk_prepare_enable(rk_phy->clk_pciephy_ref); |
230 | if (err) { | 305 | if (err) { |
231 | dev_err(&phy->dev, "Fail to enable pcie ref clock.\n"); | 306 | dev_err(&phy->dev, "Fail to enable pcie ref clock.\n"); |
@@ -238,20 +313,33 @@ static int rockchip_pcie_phy_init(struct phy *phy) | |||
238 | goto err_reset; | 313 | goto err_reset; |
239 | } | 314 | } |
240 | 315 | ||
241 | return err; | 316 | err_out: |
317 | mutex_unlock(&rk_phy->pcie_mutex); | ||
318 | return 0; | ||
242 | 319 | ||
243 | err_reset: | 320 | err_reset: |
321 | |||
244 | clk_disable_unprepare(rk_phy->clk_pciephy_ref); | 322 | clk_disable_unprepare(rk_phy->clk_pciephy_ref); |
245 | err_refclk: | 323 | err_refclk: |
324 | rk_phy->init_cnt--; | ||
325 | mutex_unlock(&rk_phy->pcie_mutex); | ||
246 | return err; | 326 | return err; |
247 | } | 327 | } |
248 | 328 | ||
249 | static int rockchip_pcie_phy_exit(struct phy *phy) | 329 | static int rockchip_pcie_phy_exit(struct phy *phy) |
250 | { | 330 | { |
251 | struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); | 331 | struct phy_pcie_instance *inst = phy_get_drvdata(phy); |
332 | struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst); | ||
333 | |||
334 | mutex_lock(&rk_phy->pcie_mutex); | ||
335 | |||
336 | if (--rk_phy->init_cnt) | ||
337 | goto err_init_cnt; | ||
252 | 338 | ||
253 | clk_disable_unprepare(rk_phy->clk_pciephy_ref); | 339 | clk_disable_unprepare(rk_phy->clk_pciephy_ref); |
254 | 340 | ||
341 | err_init_cnt: | ||
342 | mutex_unlock(&rk_phy->pcie_mutex); | ||
255 | return 0; | 343 | return 0; |
256 | } | 344 | } |
257 | 345 | ||
@@ -283,10 +371,11 @@ static int rockchip_pcie_phy_probe(struct platform_device *pdev) | |||
283 | { | 371 | { |
284 | struct device *dev = &pdev->dev; | 372 | struct device *dev = &pdev->dev; |
285 | struct rockchip_pcie_phy *rk_phy; | 373 | struct rockchip_pcie_phy *rk_phy; |
286 | struct phy *generic_phy; | ||
287 | struct phy_provider *phy_provider; | 374 | struct phy_provider *phy_provider; |
288 | struct regmap *grf; | 375 | struct regmap *grf; |
289 | const struct of_device_id *of_id; | 376 | const struct of_device_id *of_id; |
377 | int i; | ||
378 | u32 phy_num; | ||
290 | 379 | ||
291 | grf = syscon_node_to_regmap(dev->parent->of_node); | 380 | grf = syscon_node_to_regmap(dev->parent->of_node); |
292 | if (IS_ERR(grf)) { | 381 | if (IS_ERR(grf)) { |
@@ -305,6 +394,8 @@ static int rockchip_pcie_phy_probe(struct platform_device *pdev) | |||
305 | rk_phy->phy_data = (struct rockchip_pcie_data *)of_id->data; | 394 | rk_phy->phy_data = (struct rockchip_pcie_data *)of_id->data; |
306 | rk_phy->reg_base = grf; | 395 | rk_phy->reg_base = grf; |
307 | 396 | ||
397 | mutex_init(&rk_phy->pcie_mutex); | ||
398 | |||
308 | rk_phy->phy_rst = devm_reset_control_get(dev, "phy"); | 399 | rk_phy->phy_rst = devm_reset_control_get(dev, "phy"); |
309 | if (IS_ERR(rk_phy->phy_rst)) { | 400 | if (IS_ERR(rk_phy->phy_rst)) { |
310 | if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER) | 401 | if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER) |
@@ -319,14 +410,26 @@ static int rockchip_pcie_phy_probe(struct platform_device *pdev) | |||
319 | return PTR_ERR(rk_phy->clk_pciephy_ref); | 410 | return PTR_ERR(rk_phy->clk_pciephy_ref); |
320 | } | 411 | } |
321 | 412 | ||
322 | generic_phy = devm_phy_create(dev, dev->of_node, &ops); | 413 | /* parse #phy-cells to see if it's legacy PHY model */ |
323 | if (IS_ERR(generic_phy)) { | 414 | if (of_property_read_u32(dev->of_node, "#phy-cells", &phy_num)) |
324 | dev_err(dev, "failed to create PHY\n"); | 415 | return -ENOENT; |
325 | return PTR_ERR(generic_phy); | 416 | |
417 | phy_num = (phy_num == 0) ? 1 : PHY_MAX_LANE_NUM; | ||
418 | dev_dbg(dev, "phy number is %d\n", phy_num); | ||
419 | |||
420 | for (i = 0; i < phy_num; i++) { | ||
421 | rk_phy->phys[i].phy = devm_phy_create(dev, dev->of_node, &ops); | ||
422 | if (IS_ERR(rk_phy->phys[i].phy)) { | ||
423 | dev_err(dev, "failed to create PHY%d\n", i); | ||
424 | return PTR_ERR(rk_phy->phys[i].phy); | ||
425 | } | ||
426 | rk_phy->phys[i].index = i; | ||
427 | phy_set_drvdata(rk_phy->phys[i].phy, &rk_phy->phys[i]); | ||
326 | } | 428 | } |
327 | 429 | ||
328 | phy_set_drvdata(generic_phy, rk_phy); | 430 | platform_set_drvdata(pdev, rk_phy); |
329 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | 431 | phy_provider = devm_of_phy_provider_register(dev, |
432 | rockchip_pcie_phy_of_xlate); | ||
330 | 433 | ||
331 | return PTR_ERR_OR_ZERO(phy_provider); | 434 | return PTR_ERR_OR_ZERO(phy_provider); |
332 | } | 435 | } |