19
19
#include <linux/of_platform.h>
20
20
#include <linux/pci.h>
21
21
#include <linux/pci-ecam.h>
22
+ #include <linux/phy/phy.h>
22
23
#include <linux/platform_device.h>
23
24
#include <linux/irqchip/chained_irq.h>
24
25
@@ -157,6 +158,7 @@ struct nwl_pcie {
157
158
void __iomem * breg_base ;
158
159
void __iomem * pcireg_base ;
159
160
void __iomem * ecam_base ;
161
+ struct phy * phy [4 ];
160
162
phys_addr_t phys_breg_base ; /* Physical Bridge Register Base */
161
163
phys_addr_t phys_pcie_reg_base ; /* Physical PCIe Controller Base */
162
164
phys_addr_t phys_ecam_base ; /* Physical Configuration Base */
@@ -521,6 +523,60 @@ static int nwl_pcie_init_msi_irq_domain(struct nwl_pcie *pcie)
521
523
return 0 ;
522
524
}
523
525
526
+ static void nwl_pcie_phy_power_off (struct nwl_pcie * pcie , int i )
527
+ {
528
+ int err = phy_power_off (pcie -> phy [i ]);
529
+
530
+ if (err )
531
+ dev_err (pcie -> dev , "could not power off phy %d (err=%d)\n" , i ,
532
+ err );
533
+ }
534
+
535
+ static void nwl_pcie_phy_exit (struct nwl_pcie * pcie , int i )
536
+ {
537
+ int err = phy_exit (pcie -> phy [i ]);
538
+
539
+ if (err )
540
+ dev_err (pcie -> dev , "could not exit phy %d (err=%d)\n" , i , err );
541
+ }
542
+
543
+ static int nwl_pcie_phy_enable (struct nwl_pcie * pcie )
544
+ {
545
+ int i , ret ;
546
+
547
+ for (i = 0 ; i < ARRAY_SIZE (pcie -> phy ); i ++ ) {
548
+ ret = phy_init (pcie -> phy [i ]);
549
+ if (ret )
550
+ goto err ;
551
+
552
+ ret = phy_power_on (pcie -> phy [i ]);
553
+ if (ret ) {
554
+ nwl_pcie_phy_exit (pcie , i );
555
+ goto err ;
556
+ }
557
+ }
558
+
559
+ return 0 ;
560
+
561
+ err :
562
+ while (i -- ) {
563
+ nwl_pcie_phy_power_off (pcie , i );
564
+ nwl_pcie_phy_exit (pcie , i );
565
+ }
566
+
567
+ return ret ;
568
+ }
569
+
570
+ static void nwl_pcie_phy_disable (struct nwl_pcie * pcie )
571
+ {
572
+ int i ;
573
+
574
+ for (i = ARRAY_SIZE (pcie -> phy ); i -- ;) {
575
+ nwl_pcie_phy_power_off (pcie , i );
576
+ nwl_pcie_phy_exit (pcie , i );
577
+ }
578
+ }
579
+
524
580
static int nwl_pcie_init_irq_domain (struct nwl_pcie * pcie )
525
581
{
526
582
struct device * dev = pcie -> dev ;
@@ -732,6 +788,7 @@ static int nwl_pcie_parse_dt(struct nwl_pcie *pcie,
732
788
{
733
789
struct device * dev = pcie -> dev ;
734
790
struct resource * res ;
791
+ int i ;
735
792
736
793
res = platform_get_resource_byname (pdev , IORESOURCE_MEM , "breg" );
737
794
pcie -> breg_base = devm_ioremap_resource (dev , res );
@@ -759,6 +816,18 @@ static int nwl_pcie_parse_dt(struct nwl_pcie *pcie,
759
816
irq_set_chained_handler_and_data (pcie -> irq_intx ,
760
817
nwl_pcie_leg_handler , pcie );
761
818
819
+
820
+ for (i = 0 ; i < ARRAY_SIZE (pcie -> phy ); i ++ ) {
821
+ pcie -> phy [i ] = devm_of_phy_get_by_index (dev , dev -> of_node , i );
822
+ if (PTR_ERR (pcie -> phy [i ]) == - ENODEV ) {
823
+ pcie -> phy [i ] = NULL ;
824
+ break ;
825
+ }
826
+
827
+ if (IS_ERR (pcie -> phy [i ]))
828
+ return PTR_ERR (pcie -> phy [i ]);
829
+ }
830
+
762
831
return 0 ;
763
832
}
764
833
@@ -799,16 +868,22 @@ static int nwl_pcie_probe(struct platform_device *pdev)
799
868
return err ;
800
869
}
801
870
871
+ err = nwl_pcie_phy_enable (pcie );
872
+ if (err ) {
873
+ dev_err (dev , "could not enable PHYs\n" );
874
+ goto err_clk ;
875
+ }
876
+
802
877
err = nwl_pcie_bridge_init (pcie );
803
878
if (err ) {
804
879
dev_err (dev , "HW Initialization failed\n" );
805
- goto err_clk ;
880
+ goto err_phy ;
806
881
}
807
882
808
883
err = nwl_pcie_init_irq_domain (pcie );
809
884
if (err ) {
810
885
dev_err (dev , "Failed creating IRQ Domain\n" );
811
- goto err_clk ;
886
+ goto err_phy ;
812
887
}
813
888
814
889
bridge -> sysdata = pcie ;
@@ -818,14 +893,16 @@ static int nwl_pcie_probe(struct platform_device *pdev)
818
893
err = nwl_pcie_enable_msi (pcie );
819
894
if (err < 0 ) {
820
895
dev_err (dev , "failed to enable MSI support: %d\n" , err );
821
- goto err_clk ;
896
+ goto err_phy ;
822
897
}
823
898
}
824
899
825
900
err = pci_host_probe (bridge );
826
901
if (!err )
827
902
return 0 ;
828
903
904
+ err_phy :
905
+ nwl_pcie_phy_disable (pcie );
829
906
err_clk :
830
907
clk_disable_unprepare (pcie -> clk );
831
908
return err ;
@@ -835,6 +912,7 @@ static void nwl_pcie_remove(struct platform_device *pdev)
835
912
{
836
913
struct nwl_pcie * pcie = platform_get_drvdata (pdev );
837
914
915
+ nwl_pcie_phy_disable (pcie );
838
916
clk_disable_unprepare (pcie -> clk );
839
917
}
840
918
0 commit comments