diff options
Diffstat (limited to 'drivers/phy/phy-ti-pipe3.c')
-rw-r--r-- | drivers/phy/phy-ti-pipe3.c | 103 |
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 | ||
86 | static struct pipe3_dpll_map dpll_map_usb[] = { | 88 | static 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 | ||
471 | err3: | ||
472 | if (!IS_ERR(phy->wkupclk)) | ||
473 | clk_disable_unprepare(phy->wkupclk); | ||
474 | |||
417 | err2: | 475 | err2: |
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 | }; |
451 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); | 512 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); |