diff options
author | Kishon Vijay Abraham I | 2014-03-20 04:38:53 -0500 |
---|---|---|
committer | Kishon Vijay Abraham I | 2014-05-28 00:54:25 -0500 |
commit | 2b48884198b7bb9fa7309b8219c5b2e9c5fa660f (patch) | |
tree | a031e58109861c313a3bd3f57a28ac64af81f4bd | |
parent | 2b5312519f6fe690707a069844ddbcc2cf70993a (diff) | |
download | linux-phy-2b48884198b7bb9fa7309b8219c5b2e9c5fa660f.tar.gz linux-phy-2b48884198b7bb9fa7309b8219c5b2e9c5fa660f.tar.xz linux-phy-2b48884198b7bb9fa7309b8219c5b2e9c5fa660f.zip |
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>
-rw-r--r-- | Documentation/devicetree/bindings/phy/ti-phy.txt | 8 | ||||
-rw-r--r-- | drivers/phy/phy-ti-pipe3.c | 99 |
2 files changed, 84 insertions, 23 deletions
diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt index 9ce458f32945..cf3de7e9dd7a 100644 --- a/Documentation/devicetree/bindings/phy/ti-phy.txt +++ b/Documentation/devicetree/bindings/phy/ti-phy.txt | |||
@@ -56,8 +56,8 @@ usb2phy@4a0ad080 { | |||
56 | TI PIPE3 PHY | 56 | TI PIPE3 PHY |
57 | 57 | ||
58 | Required properties: | 58 | Required properties: |
59 | - compatible: Should be "ti,phy-usb3" or "ti,phy-pipe3-sata". | 59 | - compatible: Should be "ti,phy-usb3", "ti,phy-pipe3-sata" or |
60 | "ti,omap-usb3" is deprecated. | 60 | "ti,phy-pipe3-pcie. "ti,omap-usb3" is deprecated. |
61 | - reg : Address and length of the register set for the device. | 61 | - reg : Address and length of the register set for the device. |
62 | - reg-names: The names of the register addresses corresponding to the registers | 62 | - reg-names: The names of the register addresses corresponding to the registers |
63 | filled in "reg". | 63 | filled in "reg". |
@@ -69,6 +69,10 @@ Required properties: | |||
69 | * "wkupclk" - wakeup clock. | 69 | * "wkupclk" - wakeup clock. |
70 | * "sysclk" - system clock. | 70 | * "sysclk" - system clock. |
71 | * "refclk" - reference clock. | 71 | * "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 | ||
72 | 76 | ||
73 | Optional properties: | 77 | Optional properties: |
74 | - ctrl-module : phandle of the control module used by PHY driver to power on | 78 | - ctrl-module : phandle of the control module used by PHY driver to power on |
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index 591367654613..d43019d6d80a 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c | |||
@@ -80,6 +80,7 @@ struct ti_pipe3 { | |||
80 | struct clk *wkupclk; | 80 | struct clk *wkupclk; |
81 | struct clk *sys_clk; | 81 | struct clk *sys_clk; |
82 | struct clk *refclk; | 82 | struct clk *refclk; |
83 | struct clk *div_clk; | ||
83 | struct pipe3_dpll_map *dpll_map; | 84 | struct pipe3_dpll_map *dpll_map; |
84 | }; | 85 | }; |
85 | 86 | ||
@@ -215,6 +216,9 @@ static int ti_pipe3_init(struct phy *x) | |||
215 | u32 val; | 216 | u32 val; |
216 | int ret = 0; | 217 | int ret = 0; |
217 | 218 | ||
219 | if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) | ||
220 | return 0; | ||
221 | |||
218 | /* Bring it out of IDLE if it is IDLE */ | 222 | /* Bring it out of IDLE if it is IDLE */ |
219 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); | 223 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); |
220 | if (val & PLL_IDLE) { | 224 | if (val & PLL_IDLE) { |
@@ -238,8 +242,11 @@ static int ti_pipe3_exit(struct phy *x) | |||
238 | u32 val; | 242 | u32 val; |
239 | unsigned long timeout; | 243 | unsigned long timeout; |
240 | 244 | ||
241 | /* SATA DPLL can't be powered down due to Errata i783 */ | 245 | /* SATA DPLL can't be powered down due to Errata i783 and PCIe |
242 | if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) | 246 | * does not have internal DPLL |
247 | */ | ||
248 | if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") || | ||
249 | of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) | ||
243 | return 0; | 250 | return 0; |
244 | 251 | ||
245 | /* Put DPLL in IDLE mode */ | 252 | /* Put DPLL in IDLE mode */ |
@@ -286,32 +293,41 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
286 | struct device_node *control_node; | 293 | struct device_node *control_node; |
287 | struct platform_device *control_pdev; | 294 | struct platform_device *control_pdev; |
288 | const struct of_device_id *match; | 295 | const struct of_device_id *match; |
289 | 296 | struct clk *clk; | |
290 | match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev); | ||
291 | if (!match) | ||
292 | return -EINVAL; | ||
293 | 297 | ||
294 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); | 298 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); |
295 | if (!phy) { | 299 | if (!phy) { |
296 | dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n"); | 300 | dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n"); |
297 | return -ENOMEM; | 301 | return -ENOMEM; |
298 | } | 302 | } |
303 | phy->dev = &pdev->dev; | ||
299 | 304 | ||
300 | phy->dpll_map = (struct pipe3_dpll_map *)match->data; | 305 | if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { |
301 | if (!phy->dpll_map) { | 306 | match = of_match_device(of_match_ptr(ti_pipe3_id_table), |
302 | dev_err(&pdev->dev, "no DPLL data\n"); | 307 | &pdev->dev); |
303 | return -EINVAL; | 308 | if (!match) |
304 | } | 309 | return -EINVAL; |
305 | 310 | ||
306 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); | 311 | phy->dpll_map = (struct pipe3_dpll_map *)match->data; |
307 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); | 312 | if (!phy->dpll_map) { |
308 | if (IS_ERR(phy->pll_ctrl_base)) | 313 | dev_err(&pdev->dev, "no DPLL data\n"); |
309 | return PTR_ERR(phy->pll_ctrl_base); | 314 | return -EINVAL; |
315 | } | ||
310 | 316 | ||
311 | phy->dev = &pdev->dev; | 317 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
318 | "pll_ctrl"); | ||
319 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); | ||
320 | if (IS_ERR(phy->pll_ctrl_base)) | ||
321 | return PTR_ERR(phy->pll_ctrl_base); | ||
312 | 322 | ||
313 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { | 323 | phy->sys_clk = devm_clk_get(phy->dev, "sysclk"); |
324 | if (IS_ERR(phy->sys_clk)) { | ||
325 | dev_err(&pdev->dev, "unable to get sysclk\n"); | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | } | ||
314 | 329 | ||
330 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { | ||
315 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); | 331 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); |
316 | if (IS_ERR(phy->wkupclk)) { | 332 | if (IS_ERR(phy->wkupclk)) { |
317 | dev_err(&pdev->dev, "unable to get wkupclk\n"); | 333 | dev_err(&pdev->dev, "unable to get wkupclk\n"); |
@@ -328,10 +344,35 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
328 | phy->refclk = ERR_PTR(-ENODEV); | 344 | phy->refclk = ERR_PTR(-ENODEV); |
329 | } | 345 | } |
330 | 346 | ||
331 | phy->sys_clk = devm_clk_get(phy->dev, "sysclk"); | 347 | if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { |
332 | if (IS_ERR(phy->sys_clk)) { | 348 | clk = devm_clk_get(phy->dev, "dpll_ref"); |
333 | dev_err(&pdev->dev, "unable to get sysclk\n"); | 349 | if (IS_ERR(clk)) { |
334 | return -EINVAL; | 350 | dev_err(&pdev->dev, "unable to get dpll ref clk\n"); |
351 | return PTR_ERR(clk); | ||
352 | } | ||
353 | clk_set_rate(clk, 1500000000); | ||
354 | |||
355 | clk = devm_clk_get(phy->dev, "dpll_ref_m2"); | ||
356 | if (IS_ERR(clk)) { | ||
357 | dev_err(&pdev->dev, "unable to get dpll ref m2 clk\n"); | ||
358 | return PTR_ERR(clk); | ||
359 | } | ||
360 | clk_set_rate(clk, 100000000); | ||
361 | |||
362 | clk = devm_clk_get(phy->dev, "phy-div"); | ||
363 | if (IS_ERR(clk)) { | ||
364 | dev_err(&pdev->dev, "unable to get phy-div clk\n"); | ||
365 | return PTR_ERR(clk); | ||
366 | } | ||
367 | clk_set_rate(clk, 100000000); | ||
368 | |||
369 | phy->div_clk = devm_clk_get(phy->dev, "div-clk"); | ||
370 | if (IS_ERR(phy->div_clk)) { | ||
371 | dev_err(&pdev->dev, "unable to get div-clk\n"); | ||
372 | return PTR_ERR(phy->div_clk); | ||
373 | } | ||
374 | } else { | ||
375 | phy->div_clk = ERR_PTR(-ENODEV); | ||
335 | } | 376 | } |
336 | 377 | ||
337 | control_node = of_parse_phandle(node, "ctrl-module", 0); | 378 | control_node = of_parse_phandle(node, "ctrl-module", 0); |
@@ -387,6 +428,8 @@ static int ti_pipe3_runtime_suspend(struct device *dev) | |||
387 | clk_disable_unprepare(phy->wkupclk); | 428 | clk_disable_unprepare(phy->wkupclk); |
388 | if (!IS_ERR(phy->refclk)) | 429 | if (!IS_ERR(phy->refclk)) |
389 | clk_disable_unprepare(phy->refclk); | 430 | clk_disable_unprepare(phy->refclk); |
431 | if (!IS_ERR(phy->div_clk)) | ||
432 | clk_disable_unprepare(phy->div_clk); | ||
390 | 433 | ||
391 | return 0; | 434 | return 0; |
392 | } | 435 | } |
@@ -412,8 +455,19 @@ static int ti_pipe3_runtime_resume(struct device *dev) | |||
412 | } | 455 | } |
413 | } | 456 | } |
414 | 457 | ||
458 | if (!IS_ERR(phy->div_clk)) { | ||
459 | ret = clk_prepare_enable(phy->div_clk); | ||
460 | if (ret) { | ||
461 | dev_err(phy->dev, "Failed to enable div_clk %d\n", ret); | ||
462 | goto err3; | ||
463 | } | ||
464 | } | ||
415 | return 0; | 465 | return 0; |
416 | 466 | ||
467 | err3: | ||
468 | if (!IS_ERR(phy->wkupclk)) | ||
469 | clk_disable_unprepare(phy->wkupclk); | ||
470 | |||
417 | err2: | 471 | err2: |
418 | if (!IS_ERR(phy->refclk)) | 472 | if (!IS_ERR(phy->refclk)) |
419 | clk_disable_unprepare(phy->refclk); | 473 | clk_disable_unprepare(phy->refclk); |
@@ -446,6 +500,9 @@ static const struct of_device_id ti_pipe3_id_table[] = { | |||
446 | .compatible = "ti,phy-pipe3-sata", | 500 | .compatible = "ti,phy-pipe3-sata", |
447 | .data = dpll_map_sata, | 501 | .data = dpll_map_sata, |
448 | }, | 502 | }, |
503 | { | ||
504 | .compatible = "ti,phy-pipe3-pcie", | ||
505 | }, | ||
449 | {} | 506 | {} |
450 | }; | 507 | }; |
451 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); | 508 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); |