aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/controller/pci-dra7xx.c')
-rw-r--r--drivers/pci/controller/pci-dra7xx.c80
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
84struct dra7xx_pcie { 88struct 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
95struct dra7xx_pcie_of_data { 99struct 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
104struct 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
517static 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
522static 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
509static const struct of_device_id of_dra7xx_pcie_match[] = { 527static 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};
520MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match); 554MODULE_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
599static 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
565static int __init dra7xx_pcie_probe(struct platform_device *pdev) 637static 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) {