Skip to content

Commit 99bbd48

Browse files
committed
phy: phy-omap-pipe3: Add support for PCIe PHY
PCIe PHY uses an external pll instead of the internal pll used by SATA and USB3. So added support in pipe3 PHY to use external pll. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Reviewed-by: Roger Quadros <rogerq@ti.com>
1 parent 57416c2 commit 99bbd48

File tree

2 files changed

+91
-23
lines changed

2 files changed

+91
-23
lines changed

Documentation/devicetree/bindings/phy/ti-phy.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ usb2phy@4a0ad080 {
5656
TI PIPE3 PHY
5757

5858
Required properties:
59-
- compatible: Should be "ti,phy-usb3" or "ti,phy-pipe3-sata".
60-
"ti,omap-usb3" is deprecated.
59+
- compatible: Should be "ti,phy-usb3", "ti,phy-pipe3-sata" or
60+
"ti,phy-pipe3-pcie. "ti,omap-usb3" is deprecated.
6161
- reg : Address and length of the register set for the device.
6262
- reg-names: The names of the register addresses corresponding to the registers
6363
filled in "reg".
@@ -69,10 +69,17 @@ Required properties:
6969
* "wkupclk" - wakeup clock.
7070
* "sysclk" - system clock.
7171
* "refclk" - reference clock.
72+
* "dpll_ref" - external dpll ref clk
73+
* "dpll_ref_m2" - external dpll ref clk
74+
* "phy-div" - divider for apll
75+
* "div-clk" - apll clock
7276

7377
Optional properties:
7478
- ctrl-module : phandle of the control module used by PHY driver to power on
7579
the PHY.
80+
- id: If there are multiple instance of the same type, in order to
81+
differentiate between each instance "id" can be used (e.g., multi-lane PCIe
82+
PHY). If "id" is not provided, it is set to default value of '1'.
7683

7784
This is usually a subnode of ocp2scp to which it is connected.
7885

drivers/phy/phy-ti-pipe3.c

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ struct ti_pipe3 {
8080
struct clk *wkupclk;
8181
struct clk *sys_clk;
8282
struct clk *refclk;
83+
struct clk *div_clk;
8384
struct pipe3_dpll_map *dpll_map;
85+
u8 id;
8486
};
8587

8688
static struct pipe3_dpll_map dpll_map_usb[] = {
@@ -215,6 +217,9 @@ static int ti_pipe3_init(struct phy *x)
215217
u32 val;
216218
int ret = 0;
217219

220+
if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
221+
return 0;
222+
218223
/* Bring it out of IDLE if it is IDLE */
219224
val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
220225
if (val & PLL_IDLE) {
@@ -238,8 +243,11 @@ static int ti_pipe3_exit(struct phy *x)
238243
u32 val;
239244
unsigned long timeout;
240245

241-
/* SATA DPLL can't be powered down due to Errata i783 */
242-
if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
246+
/* SATA DPLL can't be powered down due to Errata i783 and PCIe
247+
* does not have internal DPLL
248+
*/
249+
if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") ||
250+
of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
243251
return 0;
244252

245253
/* Put DPLL in IDLE mode */
@@ -286,32 +294,41 @@ static int ti_pipe3_probe(struct platform_device *pdev)
286294
struct device_node *control_node;
287295
struct platform_device *control_pdev;
288296
const struct of_device_id *match;
289-
290-
match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev);
291-
if (!match)
292-
return -EINVAL;
297+
struct clk *clk;
293298

294299
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
295300
if (!phy) {
296301
dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n");
297302
return -ENOMEM;
298303
}
304+
phy->dev = &pdev->dev;
299305

300-
phy->dpll_map = (struct pipe3_dpll_map *)match->data;
301-
if (!phy->dpll_map) {
302-
dev_err(&pdev->dev, "no DPLL data\n");
303-
return -EINVAL;
304-
}
306+
if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
307+
match = of_match_device(of_match_ptr(ti_pipe3_id_table),
308+
&pdev->dev);
309+
if (!match)
310+
return -EINVAL;
305311

306-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
307-
phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
308-
if (IS_ERR(phy->pll_ctrl_base))
309-
return PTR_ERR(phy->pll_ctrl_base);
312+
phy->dpll_map = (struct pipe3_dpll_map *)match->data;
313+
if (!phy->dpll_map) {
314+
dev_err(&pdev->dev, "no DPLL data\n");
315+
return -EINVAL;
316+
}
310317

311-
phy->dev = &pdev->dev;
318+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
319+
"pll_ctrl");
320+
phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
321+
if (IS_ERR(phy->pll_ctrl_base))
322+
return PTR_ERR(phy->pll_ctrl_base);
312323

313-
if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
324+
phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
325+
if (IS_ERR(phy->sys_clk)) {
326+
dev_err(&pdev->dev, "unable to get sysclk\n");
327+
return -EINVAL;
328+
}
329+
}
314330

331+
if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
315332
phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
316333
if (IS_ERR(phy->wkupclk)) {
317334
dev_err(&pdev->dev, "unable to get wkupclk\n");
@@ -328,10 +345,38 @@ static int ti_pipe3_probe(struct platform_device *pdev)
328345
phy->refclk = ERR_PTR(-ENODEV);
329346
}
330347

331-
phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
332-
if (IS_ERR(phy->sys_clk)) {
333-
dev_err(&pdev->dev, "unable to get sysclk\n");
334-
return -EINVAL;
348+
if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
349+
if (of_property_read_u8(node, "id", &phy->id) < 0)
350+
phy->id = 1;
351+
352+
clk = devm_clk_get(phy->dev, "dpll_ref");
353+
if (IS_ERR(clk)) {
354+
dev_err(&pdev->dev, "unable to get dpll ref clk\n");
355+
return PTR_ERR(clk);
356+
}
357+
clk_set_rate(clk, 1500000000);
358+
359+
clk = devm_clk_get(phy->dev, "dpll_ref_m2");
360+
if (IS_ERR(clk)) {
361+
dev_err(&pdev->dev, "unable to get dpll ref m2 clk\n");
362+
return PTR_ERR(clk);
363+
}
364+
clk_set_rate(clk, 100000000);
365+
366+
clk = devm_clk_get(phy->dev, "phy-div");
367+
if (IS_ERR(clk)) {
368+
dev_err(&pdev->dev, "unable to get phy-div clk\n");
369+
return PTR_ERR(clk);
370+
}
371+
clk_set_rate(clk, 100000000);
372+
373+
phy->div_clk = devm_clk_get(phy->dev, "div-clk");
374+
if (IS_ERR(phy->div_clk)) {
375+
dev_err(&pdev->dev, "unable to get div-clk\n");
376+
return PTR_ERR(phy->div_clk);
377+
}
378+
} else {
379+
phy->div_clk = ERR_PTR(-ENODEV);
335380
}
336381

337382
control_node = of_parse_phandle(node, "ctrl-module", 0);
@@ -387,6 +432,8 @@ static int ti_pipe3_runtime_suspend(struct device *dev)
387432
clk_disable_unprepare(phy->wkupclk);
388433
if (!IS_ERR(phy->refclk))
389434
clk_disable_unprepare(phy->refclk);
435+
if (!IS_ERR(phy->div_clk))
436+
clk_disable_unprepare(phy->div_clk);
390437

391438
return 0;
392439
}
@@ -412,8 +459,19 @@ static int ti_pipe3_runtime_resume(struct device *dev)
412459
}
413460
}
414461

462+
if (!IS_ERR(phy->div_clk)) {
463+
ret = clk_prepare_enable(phy->div_clk);
464+
if (ret) {
465+
dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
466+
goto err3;
467+
}
468+
}
415469
return 0;
416470

471+
err3:
472+
if (!IS_ERR(phy->wkupclk))
473+
clk_disable_unprepare(phy->wkupclk);
474+
417475
err2:
418476
if (!IS_ERR(phy->refclk))
419477
clk_disable_unprepare(phy->refclk);
@@ -446,6 +504,9 @@ static const struct of_device_id ti_pipe3_id_table[] = {
446504
.compatible = "ti,phy-pipe3-sata",
447505
.data = dpll_map_sata,
448506
},
507+
{
508+
.compatible = "ti,phy-pipe3-pcie",
509+
},
449510
{}
450511
};
451512
MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);

0 commit comments

Comments
 (0)