diff options
Diffstat (limited to 'drivers/pci/controller/pci-dra7xx.c')
-rw-r--r-- | drivers/pci/controller/pci-dra7xx.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/pci/controller/pci-dra7xx.c b/drivers/pci/controller/pci-dra7xx.c index d60d4cf20516..330866f9b924 100644 --- a/drivers/pci/controller/pci-dra7xx.c +++ b/drivers/pci/controller/pci-dra7xx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/of_gpio.h> | 20 | #include <linux/of_gpio.h> |
21 | #include <linux/of_device.h> | 21 | #include <linux/of_device.h> |
22 | #include <linux/of_platform.h> | ||
22 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
23 | #include <linux/phy/phy.h> | 24 | #include <linux/phy/phy.h> |
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
@@ -81,6 +82,9 @@ | |||
81 | #define MSI_REQ_GRANT BIT(0) | 82 | #define MSI_REQ_GRANT BIT(0) |
82 | #define MSI_VECTOR_SHIFT 7 | 83 | #define MSI_VECTOR_SHIFT 7 |
83 | 84 | ||
85 | #define PCIE_1LANE_2LANE_SELECTION BIT(13) | ||
86 | #define PCIE_B1C0_MODE_SEL BIT(2) | ||
87 | |||
84 | struct dra7xx_pcie { | 88 | struct dra7xx_pcie { |
85 | void __iomem *base; | 89 | void __iomem *base; |
86 | struct phy **phy; | 90 | struct phy **phy; |
@@ -94,6 +98,10 @@ struct dra7xx_pcie { | |||
94 | 98 | ||
95 | struct dra7xx_pcie_of_data { | 99 | struct dra7xx_pcie_of_data { |
96 | enum dw_pcie_device_mode mode; | 100 | enum dw_pcie_device_mode mode; |
101 | u32 b1co_mode_sel_mask; | ||
102 | }; | ||
103 | |||
104 | struct dra7xx_pcie_data { | ||
97 | }; | 105 | }; |
98 | 106 | ||
99 | #define to_dra7xx_pcie(x) dev_get_drvdata((x)->dev) | 107 | #define to_dra7xx_pcie(x) dev_get_drvdata((x)->dev) |
@@ -506,6 +514,16 @@ static const struct dra7xx_pcie_of_data dra7xx_pcie_ep_of_data = { | |||
506 | .mode = DW_PCIE_EP_TYPE, | 514 | .mode = DW_PCIE_EP_TYPE, |
507 | }; | 515 | }; |
508 | 516 | ||
517 | static const struct dra7xx_pcie_of_data dra746_pcie_rc_of_data = { | ||
518 | .b1co_mode_sel_mask = BIT(2), | ||
519 | .mode = DW_PCIE_RC_TYPE, | ||
520 | }; | ||
521 | |||
522 | static const struct dra7xx_pcie_of_data dra746_pcie_ep_of_data = { | ||
523 | .b1co_mode_sel_mask = BIT(2), | ||
524 | .mode = DW_PCIE_EP_TYPE, | ||
525 | }; | ||
526 | |||
509 | static const struct of_device_id of_dra7xx_pcie_match[] = { | 527 | static const struct of_device_id of_dra7xx_pcie_match[] = { |
510 | { | 528 | { |
511 | .compatible = "ti,dra7-pcie", | 529 | .compatible = "ti,dra7-pcie", |
@@ -515,6 +533,22 @@ static const struct of_device_id of_dra7xx_pcie_match[] = { | |||
515 | .compatible = "ti,dra7-pcie-ep", | 533 | .compatible = "ti,dra7-pcie-ep", |
516 | .data = &dra7xx_pcie_ep_of_data, | 534 | .data = &dra7xx_pcie_ep_of_data, |
517 | }, | 535 | }, |
536 | { | ||
537 | .compatible = "ti,dra746-pcie-rc", | ||
538 | .data = &dra746_pcie_rc_of_data, | ||
539 | }, | ||
540 | { | ||
541 | .compatible = "ti,dra746-pcie-ep", | ||
542 | .data = &dra746_pcie_ep_of_data, | ||
543 | }, | ||
544 | { | ||
545 | .compatible = "ti,dra726-pcie-rc", | ||
546 | .data = &dra7xx_pcie_rc_of_data, | ||
547 | }, | ||
548 | { | ||
549 | .compatible = "ti,dra726-pcie-ep", | ||
550 | .data = &dra7xx_pcie_ep_of_data, | ||
551 | }, | ||
518 | {}, | 552 | {}, |
519 | }; | 553 | }; |
520 | MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match); | 554 | MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match); |
@@ -562,6 +596,44 @@ static int dra7xx_pcie_ep_legacy_mode(struct dra7xx_pcie *dra7xx) | |||
562 | return ret; | 596 | return ret; |
563 | } | 597 | } |
564 | 598 | ||
599 | static int dra7xx_pcie_configure_two_lane(struct device *dev, | ||
600 | u32 b1co_mode_sel_mask) | ||
601 | { | ||
602 | struct device_node *np = dev->of_node; | ||
603 | struct regmap *pcie_syscon; | ||
604 | unsigned int pcie_reg; | ||
605 | |||
606 | pcie_syscon = syscon_regmap_lookup_by_phandle(np, "syscon-lane-conf"); | ||
607 | if (IS_ERR(pcie_syscon)) { | ||
608 | dev_err(dev, "unable to get syscon-lane-conf\n"); | ||
609 | return -EINVAL; | ||
610 | } | ||
611 | |||
612 | if (of_property_read_u32_index(np, "syscon-lane-conf", 1, &pcie_reg)) { | ||
613 | dev_err(dev, "couldn't get lane configuration reg offset\n"); | ||
614 | return -EINVAL; | ||
615 | } | ||
616 | |||
617 | regmap_update_bits(pcie_syscon, pcie_reg, PCIE_1LANE_2LANE_SELECTION, | ||
618 | PCIE_1LANE_2LANE_SELECTION); | ||
619 | |||
620 | pcie_syscon = syscon_regmap_lookup_by_phandle(np, "syscon-lane-sel"); | ||
621 | if (IS_ERR(pcie_syscon)) { | ||
622 | dev_err(dev, "unable to get syscon-lane-sel\n"); | ||
623 | return -EINVAL; | ||
624 | } | ||
625 | |||
626 | if (of_property_read_u32_index(np, "syscon-lane-sel", 1, &pcie_reg)) { | ||
627 | dev_err(dev, "couldn't get lane selection reg offset\n"); | ||
628 | return -EINVAL; | ||
629 | } | ||
630 | |||
631 | regmap_update_bits(pcie_syscon, pcie_reg, b1co_mode_sel_mask, | ||
632 | PCIE_B1C0_MODE_SEL); | ||
633 | |||
634 | return 0; | ||
635 | } | ||
636 | |||
565 | static int __init dra7xx_pcie_probe(struct platform_device *pdev) | 637 | static int __init dra7xx_pcie_probe(struct platform_device *pdev) |
566 | { | 638 | { |
567 | u32 reg; | 639 | u32 reg; |
@@ -581,6 +653,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) | |||
581 | const struct of_device_id *match; | 653 | const struct of_device_id *match; |
582 | const struct dra7xx_pcie_of_data *data; | 654 | const struct dra7xx_pcie_of_data *data; |
583 | enum dw_pcie_device_mode mode; | 655 | enum dw_pcie_device_mode mode; |
656 | u32 b1co_mode_sel_mask; | ||
584 | 657 | ||
585 | match = of_match_device(of_match_ptr(of_dra7xx_pcie_match), dev); | 658 | match = of_match_device(of_match_ptr(of_dra7xx_pcie_match), dev); |
586 | if (!match) | 659 | if (!match) |
@@ -588,6 +661,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) | |||
588 | 661 | ||
589 | data = (struct dra7xx_pcie_of_data *)match->data; | 662 | data = (struct dra7xx_pcie_of_data *)match->data; |
590 | mode = (enum dw_pcie_device_mode)data->mode; | 663 | mode = (enum dw_pcie_device_mode)data->mode; |
664 | b1co_mode_sel_mask = data->b1co_mode_sel_mask; | ||
591 | 665 | ||
592 | dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL); | 666 | dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL); |
593 | if (!dra7xx) | 667 | if (!dra7xx) |
@@ -651,6 +725,12 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) | |||
651 | dra7xx->dev = dev; | 725 | dra7xx->dev = dev; |
652 | dra7xx->phy_count = phy_count; | 726 | dra7xx->phy_count = phy_count; |
653 | 727 | ||
728 | if (phy_count == 2) { | ||
729 | ret = dra7xx_pcie_configure_two_lane(dev, b1co_mode_sel_mask); | ||
730 | if (ret < 0) | ||
731 | goto err_phy; | ||
732 | } | ||
733 | |||
654 | pm_runtime_enable(dev); | 734 | pm_runtime_enable(dev); |
655 | ret = pm_runtime_get_sync(dev); | 735 | ret = pm_runtime_get_sync(dev); |
656 | if (ret < 0) { | 736 | if (ret < 0) { |