aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy/phy-ti-pipe3.c
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2014-06-25 13:52:56 -0400
committerKishon Vijay Abraham I <kishon@ti.com>2014-07-22 03:16:10 -0400
commit99bbd48c2065552fd2d224c9f065dcac9b7e25ce (patch)
tree472b73a962d52f4d809353fbac2375dd5c0462fe /drivers/phy/phy-ti-pipe3.c
parent57416c23e3ab57e65ba6e7c2e30fb40ba85035a6 (diff)
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>
Diffstat (limited to 'drivers/phy/phy-ti-pipe3.c')
-rw-r--r--drivers/phy/phy-ti-pipe3.c103
1 files changed, 82 insertions, 21 deletions
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 591367654613..6174f4b1a5de 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -80,7 +80,9 @@ 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;
85 u8 id;
84}; 86};
85 87
86static struct pipe3_dpll_map dpll_map_usb[] = { 88static struct pipe3_dpll_map dpll_map_usb[] = {
@@ -215,6 +217,9 @@ static int ti_pipe3_init(struct phy *x)
215 u32 val; 217 u32 val;
216 int ret = 0; 218 int ret = 0;
217 219
220 if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
221 return 0;
222
218 /* Bring it out of IDLE if it is IDLE */ 223 /* Bring it out of IDLE if it is IDLE */
219 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); 224 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
220 if (val & PLL_IDLE) { 225 if (val & PLL_IDLE) {
@@ -238,8 +243,11 @@ static int ti_pipe3_exit(struct phy *x)
238 u32 val; 243 u32 val;
239 unsigned long timeout; 244 unsigned long timeout;
240 245
241 /* SATA DPLL can't be powered down due to Errata i783 */ 246 /* 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")) 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"))
243 return 0; 251 return 0;
244 252
245 /* Put DPLL in IDLE mode */ 253 /* Put DPLL in IDLE mode */
@@ -286,32 +294,41 @@ static int ti_pipe3_probe(struct platform_device *pdev)
286 struct device_node *control_node; 294 struct device_node *control_node;
287 struct platform_device *control_pdev; 295 struct platform_device *control_pdev;
288 const struct of_device_id *match; 296 const struct of_device_id *match;
289 297 struct clk *clk;
290 match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev);
291 if (!match)
292 return -EINVAL;
293 298
294 phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); 299 phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
295 if (!phy) { 300 if (!phy) {
296 dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n"); 301 dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n");
297 return -ENOMEM; 302 return -ENOMEM;
298 } 303 }
304 phy->dev = &pdev->dev;
299 305
300 phy->dpll_map = (struct pipe3_dpll_map *)match->data; 306 if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
301 if (!phy->dpll_map) { 307 match = of_match_device(of_match_ptr(ti_pipe3_id_table),
302 dev_err(&pdev->dev, "no DPLL data\n"); 308 &pdev->dev);
303 return -EINVAL; 309 if (!match)
304 } 310 return -EINVAL;
305 311
306 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); 312 phy->dpll_map = (struct pipe3_dpll_map *)match->data;
307 phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); 313 if (!phy->dpll_map) {
308 if (IS_ERR(phy->pll_ctrl_base)) 314 dev_err(&pdev->dev, "no DPLL data\n");
309 return PTR_ERR(phy->pll_ctrl_base); 315 return -EINVAL;
316 }
310 317
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);
312 323
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 }
314 330
331 if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
315 phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); 332 phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
316 if (IS_ERR(phy->wkupclk)) { 333 if (IS_ERR(phy->wkupclk)) {
317 dev_err(&pdev->dev, "unable to get wkupclk\n"); 334 dev_err(&pdev->dev, "unable to get wkupclk\n");
@@ -328,10 +345,38 @@ static int ti_pipe3_probe(struct platform_device *pdev)
328 phy->refclk = ERR_PTR(-ENODEV); 345 phy->refclk = ERR_PTR(-ENODEV);
329 } 346 }
330 347
331 phy->sys_clk = devm_clk_get(phy->dev, "sysclk"); 348 if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
332 if (IS_ERR(phy->sys_clk)) { 349 if (of_property_read_u8(node, "id", &phy->id) < 0)
333 dev_err(&pdev->dev, "unable to get sysclk\n"); 350 phy->id = 1;
334 return -EINVAL; 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);
335 } 380 }
336 381
337 control_node = of_parse_phandle(node, "ctrl-module", 0); 382 control_node = of_parse_phandle(node, "ctrl-module", 0);
@@ -387,6 +432,8 @@ static int ti_pipe3_runtime_suspend(struct device *dev)
387 clk_disable_unprepare(phy->wkupclk); 432 clk_disable_unprepare(phy->wkupclk);
388 if (!IS_ERR(phy->refclk)) 433 if (!IS_ERR(phy->refclk))
389 clk_disable_unprepare(phy->refclk); 434 clk_disable_unprepare(phy->refclk);
435 if (!IS_ERR(phy->div_clk))
436 clk_disable_unprepare(phy->div_clk);
390 437
391 return 0; 438 return 0;
392} 439}
@@ -412,8 +459,19 @@ static int ti_pipe3_runtime_resume(struct device *dev)
412 } 459 }
413 } 460 }
414 461
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 }
415 return 0; 469 return 0;
416 470
471err3:
472 if (!IS_ERR(phy->wkupclk))
473 clk_disable_unprepare(phy->wkupclk);
474
417err2: 475err2:
418 if (!IS_ERR(phy->refclk)) 476 if (!IS_ERR(phy->refclk))
419 clk_disable_unprepare(phy->refclk); 477 clk_disable_unprepare(phy->refclk);
@@ -446,6 +504,9 @@ static const struct of_device_id ti_pipe3_id_table[] = {
446 .compatible = "ti,phy-pipe3-sata", 504 .compatible = "ti,phy-pipe3-sata",
447 .data = dpll_map_sata, 505 .data = dpll_map_sata,
448 }, 506 },
507 {
508 .compatible = "ti,phy-pipe3-pcie",
509 },
449 {} 510 {}
450}; 511};
451MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); 512MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);