aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKishon Vijay Abraham I2014-03-20 04:38:53 -0500
committerKishon Vijay Abraham I2014-05-28 00:54:25 -0500
commit2b48884198b7bb9fa7309b8219c5b2e9c5fa660f (patch)
treea031e58109861c313a3bd3f57a28ac64af81f4bd
parent2b5312519f6fe690707a069844ddbcc2cf70993a (diff)
downloadlinux-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.txt8
-rw-r--r--drivers/phy/phy-ti-pipe3.c99
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 {
56TI PIPE3 PHY 56TI PIPE3 PHY
57 57
58Required properties: 58Required 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
73Optional properties: 77Optional 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
467err3:
468 if (!IS_ERR(phy->wkupclk))
469 clk_disable_unprepare(phy->wkupclk);
470
417err2: 471err2:
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};
451MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); 508MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);