| .. | .. |
|---|
| 12 | 12 | #include <linux/module.h> |
|---|
| 13 | 13 | #include <linux/of_platform.h> |
|---|
| 14 | 14 | #include <linux/platform_device.h> |
|---|
| 15 | | -#include <linux/pm_clock.h> |
|---|
| 16 | 15 | #include <linux/pm_runtime.h> |
|---|
| 16 | + |
|---|
| 17 | +struct tegra_aconnect { |
|---|
| 18 | + struct clk *ape_clk; |
|---|
| 19 | + struct clk *apb2ape_clk; |
|---|
| 20 | +}; |
|---|
| 17 | 21 | |
|---|
| 18 | 22 | static int tegra_aconnect_probe(struct platform_device *pdev) |
|---|
| 19 | 23 | { |
|---|
| 20 | | - int ret; |
|---|
| 24 | + struct tegra_aconnect *aconnect; |
|---|
| 21 | 25 | |
|---|
| 22 | 26 | if (!pdev->dev.of_node) |
|---|
| 23 | 27 | return -EINVAL; |
|---|
| 24 | 28 | |
|---|
| 25 | | - ret = pm_clk_create(&pdev->dev); |
|---|
| 26 | | - if (ret) |
|---|
| 27 | | - return ret; |
|---|
| 29 | + aconnect = devm_kzalloc(&pdev->dev, sizeof(struct tegra_aconnect), |
|---|
| 30 | + GFP_KERNEL); |
|---|
| 31 | + if (!aconnect) |
|---|
| 32 | + return -ENOMEM; |
|---|
| 28 | 33 | |
|---|
| 29 | | - ret = of_pm_clk_add_clk(&pdev->dev, "ape"); |
|---|
| 30 | | - if (ret) |
|---|
| 31 | | - goto clk_destroy; |
|---|
| 34 | + aconnect->ape_clk = devm_clk_get(&pdev->dev, "ape"); |
|---|
| 35 | + if (IS_ERR(aconnect->ape_clk)) { |
|---|
| 36 | + dev_err(&pdev->dev, "Can't retrieve ape clock\n"); |
|---|
| 37 | + return PTR_ERR(aconnect->ape_clk); |
|---|
| 38 | + } |
|---|
| 32 | 39 | |
|---|
| 33 | | - ret = of_pm_clk_add_clk(&pdev->dev, "apb2ape"); |
|---|
| 34 | | - if (ret) |
|---|
| 35 | | - goto clk_destroy; |
|---|
| 40 | + aconnect->apb2ape_clk = devm_clk_get(&pdev->dev, "apb2ape"); |
|---|
| 41 | + if (IS_ERR(aconnect->apb2ape_clk)) { |
|---|
| 42 | + dev_err(&pdev->dev, "Can't retrieve apb2ape clock\n"); |
|---|
| 43 | + return PTR_ERR(aconnect->apb2ape_clk); |
|---|
| 44 | + } |
|---|
| 36 | 45 | |
|---|
| 46 | + dev_set_drvdata(&pdev->dev, aconnect); |
|---|
| 37 | 47 | pm_runtime_enable(&pdev->dev); |
|---|
| 38 | 48 | |
|---|
| 39 | 49 | of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); |
|---|
| .. | .. |
|---|
| 41 | 51 | dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n"); |
|---|
| 42 | 52 | |
|---|
| 43 | 53 | return 0; |
|---|
| 44 | | - |
|---|
| 45 | | -clk_destroy: |
|---|
| 46 | | - pm_clk_destroy(&pdev->dev); |
|---|
| 47 | | - |
|---|
| 48 | | - return ret; |
|---|
| 49 | 54 | } |
|---|
| 50 | 55 | |
|---|
| 51 | 56 | static int tegra_aconnect_remove(struct platform_device *pdev) |
|---|
| 52 | 57 | { |
|---|
| 53 | 58 | pm_runtime_disable(&pdev->dev); |
|---|
| 54 | 59 | |
|---|
| 55 | | - pm_clk_destroy(&pdev->dev); |
|---|
| 56 | | - |
|---|
| 57 | 60 | return 0; |
|---|
| 58 | 61 | } |
|---|
| 59 | 62 | |
|---|
| 60 | 63 | static int tegra_aconnect_runtime_resume(struct device *dev) |
|---|
| 61 | 64 | { |
|---|
| 62 | | - return pm_clk_resume(dev); |
|---|
| 65 | + struct tegra_aconnect *aconnect = dev_get_drvdata(dev); |
|---|
| 66 | + int ret; |
|---|
| 67 | + |
|---|
| 68 | + ret = clk_prepare_enable(aconnect->ape_clk); |
|---|
| 69 | + if (ret) { |
|---|
| 70 | + dev_err(dev, "ape clk_enable failed: %d\n", ret); |
|---|
| 71 | + return ret; |
|---|
| 72 | + } |
|---|
| 73 | + |
|---|
| 74 | + ret = clk_prepare_enable(aconnect->apb2ape_clk); |
|---|
| 75 | + if (ret) { |
|---|
| 76 | + clk_disable_unprepare(aconnect->ape_clk); |
|---|
| 77 | + dev_err(dev, "apb2ape clk_enable failed: %d\n", ret); |
|---|
| 78 | + return ret; |
|---|
| 79 | + } |
|---|
| 80 | + |
|---|
| 81 | + return 0; |
|---|
| 63 | 82 | } |
|---|
| 64 | 83 | |
|---|
| 65 | 84 | static int tegra_aconnect_runtime_suspend(struct device *dev) |
|---|
| 66 | 85 | { |
|---|
| 67 | | - return pm_clk_suspend(dev); |
|---|
| 86 | + struct tegra_aconnect *aconnect = dev_get_drvdata(dev); |
|---|
| 87 | + |
|---|
| 88 | + clk_disable_unprepare(aconnect->ape_clk); |
|---|
| 89 | + clk_disable_unprepare(aconnect->apb2ape_clk); |
|---|
| 90 | + |
|---|
| 91 | + return 0; |
|---|
| 68 | 92 | } |
|---|
| 69 | 93 | |
|---|
| 70 | 94 | static const struct dev_pm_ops tegra_aconnect_pm_ops = { |
|---|
| 71 | 95 | SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend, |
|---|
| 72 | 96 | tegra_aconnect_runtime_resume, NULL) |
|---|
| 97 | + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, |
|---|
| 98 | + pm_runtime_force_resume) |
|---|
| 73 | 99 | }; |
|---|
| 74 | 100 | |
|---|
| 75 | 101 | static const struct of_device_id tegra_aconnect_of_match[] = { |
|---|