16
16
#include <linux/reset.h>
17
17
#include <linux/resource.h>
18
18
#include <linux/types.h>
19
+ #include <linux/phy/phy.h>
19
20
20
21
#include "pcie-designware.h"
21
22
@@ -96,12 +97,18 @@ struct meson_pcie_rc_reset {
96
97
struct reset_control * apb ;
97
98
};
98
99
100
+ struct meson_pcie_param {
101
+ bool has_shared_phy ;
102
+ };
103
+
99
104
struct meson_pcie {
100
105
struct dw_pcie pci ;
101
106
struct meson_pcie_mem_res mem_res ;
102
107
struct meson_pcie_clk_res clk_res ;
103
108
struct meson_pcie_rc_reset mrst ;
104
109
struct gpio_desc * reset_gpio ;
110
+ struct phy * phy ;
111
+ const struct meson_pcie_param * param ;
105
112
};
106
113
107
114
static struct reset_control * meson_pcie_get_reset (struct meson_pcie * mp ,
@@ -123,10 +130,12 @@ static int meson_pcie_get_resets(struct meson_pcie *mp)
123
130
{
124
131
struct meson_pcie_rc_reset * mrst = & mp -> mrst ;
125
132
126
- mrst -> phy = meson_pcie_get_reset (mp , "phy" , PCIE_SHARED_RESET );
127
- if (IS_ERR (mrst -> phy ))
128
- return PTR_ERR (mrst -> phy );
129
- reset_control_deassert (mrst -> phy );
133
+ if (!mp -> param -> has_shared_phy ) {
134
+ mrst -> phy = meson_pcie_get_reset (mp , "phy" , PCIE_SHARED_RESET );
135
+ if (IS_ERR (mrst -> phy ))
136
+ return PTR_ERR (mrst -> phy );
137
+ reset_control_deassert (mrst -> phy );
138
+ }
130
139
131
140
mrst -> port = meson_pcie_get_reset (mp , "port" , PCIE_NORMAL_RESET );
132
141
if (IS_ERR (mrst -> port ))
@@ -180,34 +189,61 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
180
189
if (IS_ERR (mp -> mem_res .cfg_base ))
181
190
return PTR_ERR (mp -> mem_res .cfg_base );
182
191
183
- /* Meson SoC has two PCI controllers use same phy register*/
184
- mp -> mem_res .phy_base = meson_pcie_get_mem_shared (pdev , mp , "phy" );
185
- if (IS_ERR (mp -> mem_res .phy_base ))
186
- return PTR_ERR (mp -> mem_res .phy_base );
192
+ /* Meson AXG SoC has two PCI controllers use same phy register */
193
+ if (!mp -> param -> has_shared_phy ) {
194
+ mp -> mem_res .phy_base =
195
+ meson_pcie_get_mem_shared (pdev , mp , "phy" );
196
+ if (IS_ERR (mp -> mem_res .phy_base ))
197
+ return PTR_ERR (mp -> mem_res .phy_base );
198
+ }
187
199
188
200
return 0 ;
189
201
}
190
202
191
- static void meson_pcie_power_on (struct meson_pcie * mp )
203
+ static int meson_pcie_power_on (struct meson_pcie * mp )
192
204
{
193
- writel (MESON_PCIE_PHY_POWERUP , mp -> mem_res .phy_base );
205
+ int ret = 0 ;
206
+
207
+ if (mp -> param -> has_shared_phy ) {
208
+ ret = phy_init (mp -> phy );
209
+ if (ret )
210
+ return ret ;
211
+
212
+ ret = phy_power_on (mp -> phy );
213
+ if (ret ) {
214
+ phy_exit (mp -> phy );
215
+ return ret ;
216
+ }
217
+ } else
218
+ writel (MESON_PCIE_PHY_POWERUP , mp -> mem_res .phy_base );
219
+
220
+ return 0 ;
194
221
}
195
222
196
- static void meson_pcie_reset (struct meson_pcie * mp )
223
+ static int meson_pcie_reset (struct meson_pcie * mp )
197
224
{
198
225
struct meson_pcie_rc_reset * mrst = & mp -> mrst ;
199
-
200
- reset_control_assert (mrst -> phy );
201
- udelay (PCIE_RESET_DELAY );
202
- reset_control_deassert (mrst -> phy );
203
- udelay (PCIE_RESET_DELAY );
226
+ int ret = 0 ;
227
+
228
+ if (mp -> param -> has_shared_phy ) {
229
+ ret = phy_reset (mp -> phy );
230
+ if (ret )
231
+ return ret ;
232
+ } else {
233
+ reset_control_assert (mrst -> phy );
234
+ udelay (PCIE_RESET_DELAY );
235
+ reset_control_deassert (mrst -> phy );
236
+ udelay (PCIE_RESET_DELAY );
237
+ }
204
238
205
239
reset_control_assert (mrst -> port );
206
240
reset_control_assert (mrst -> apb );
207
241
udelay (PCIE_RESET_DELAY );
208
242
reset_control_deassert (mrst -> port );
209
243
reset_control_deassert (mrst -> apb );
210
244
udelay (PCIE_RESET_DELAY );
245
+
246
+ return 0 ;
211
247
}
212
248
213
249
static inline struct clk * meson_pcie_probe_clock (struct device * dev ,
@@ -250,9 +286,11 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp)
250
286
if (IS_ERR (res -> port_clk ))
251
287
return PTR_ERR (res -> port_clk );
252
288
253
- res -> mipi_gate = meson_pcie_probe_clock (dev , "mipi" , 0 );
254
- if (IS_ERR (res -> mipi_gate ))
255
- return PTR_ERR (res -> mipi_gate );
289
+ if (!mp -> param -> has_shared_phy ) {
290
+ res -> mipi_gate = meson_pcie_probe_clock (dev , "mipi" , 0 );
291
+ if (IS_ERR (res -> mipi_gate ))
292
+ return PTR_ERR (res -> mipi_gate );
293
+ }
256
294
257
295
res -> general_clk = meson_pcie_probe_clock (dev , "general" , 0 );
258
296
if (IS_ERR (res -> general_clk ))
@@ -524,6 +562,7 @@ static const struct dw_pcie_ops dw_pcie_ops = {
524
562
525
563
static int meson_pcie_probe (struct platform_device * pdev )
526
564
{
565
+ const struct meson_pcie_param * match_data ;
527
566
struct device * dev = & pdev -> dev ;
528
567
struct dw_pcie * pci ;
529
568
struct meson_pcie * mp ;
@@ -537,6 +576,19 @@ static int meson_pcie_probe(struct platform_device *pdev)
537
576
pci -> dev = dev ;
538
577
pci -> ops = & dw_pcie_ops ;
539
578
579
+ match_data = of_device_get_match_data (dev );
580
+ if (!match_data ) {
581
+ dev_err (dev , "failed to get match data\n" );
582
+ return - ENODEV ;
583
+ }
584
+ mp -> param = match_data ;
585
+
586
+ if (mp -> param -> has_shared_phy ) {
587
+ mp -> phy = devm_phy_get (dev , "pcie" );
588
+ if (IS_ERR (mp -> phy ))
589
+ return PTR_ERR (mp -> phy );
590
+ }
591
+
540
592
mp -> reset_gpio = devm_gpiod_get (dev , "reset" , GPIOD_OUT_LOW );
541
593
if (IS_ERR (mp -> reset_gpio )) {
542
594
dev_err (dev , "get reset gpio failed\n" );
@@ -555,29 +607,59 @@ static int meson_pcie_probe(struct platform_device *pdev)
555
607
return ret ;
556
608
}
557
609
558
- meson_pcie_power_on (mp );
559
- meson_pcie_reset (mp );
610
+ ret = meson_pcie_power_on (mp );
611
+ if (ret ) {
612
+ dev_err (dev , "phy power on failed, %d\n" , ret );
613
+ return ret ;
614
+ }
615
+
616
+ ret = meson_pcie_reset (mp );
617
+ if (ret ) {
618
+ dev_err (dev , "reset failed, %d\n" , ret );
619
+ goto err_phy ;
620
+ }
560
621
561
622
ret = meson_pcie_probe_clocks (mp );
562
623
if (ret ) {
563
624
dev_err (dev , "init clock resources failed, %d\n" , ret );
564
- return ret ;
625
+ goto err_phy ;
565
626
}
566
627
567
628
platform_set_drvdata (pdev , mp );
568
629
569
630
ret = meson_add_pcie_port (mp , pdev );
570
631
if (ret < 0 ) {
571
632
dev_err (dev , "Add PCIe port failed, %d\n" , ret );
572
- return ret ;
633
+ goto err_phy ;
573
634
}
574
635
575
636
return 0 ;
637
+
638
+ err_phy :
639
+ if (mp -> param -> has_shared_phy ) {
640
+ phy_power_off (mp -> phy );
641
+ phy_exit (mp -> phy );
642
+ }
643
+
644
+ return ret ;
576
645
}
577
646
647
+ static struct meson_pcie_param meson_pcie_axg_param = {
648
+ .has_shared_phy = false,
649
+ };
650
+
651
+ static struct meson_pcie_param meson_pcie_g12a_param = {
652
+ .has_shared_phy = true,
653
+ };
654
+
578
655
static const struct of_device_id meson_pcie_of_match [] = {
579
656
{
580
657
.compatible = "amlogic,axg-pcie" ,
658
+ .data = & meson_pcie_axg_param ,
659
+ },
660
+ {
661
+ .compatible = "amlogic,g12a-pcie" ,
662
+ .data = & meson_pcie_g12a_param ,
581
663
},
582
664
{},
583
665
};
0 commit comments