diff options
| author | Olof Johansson <olof@lixom.net> | 2019-04-29 02:33:19 -0400 |
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2019-04-29 02:33:19 -0400 |
| commit | fea188820b3850268571b66cb5b4837009b3fe97 (patch) | |
| tree | 361d8af084bfbd08183e810bbb9ea17a9d0c3a9d | |
| parent | aaf75f2b53b7dfbc99b85b9707ffd4115cfce7ac (diff) | |
| parent | 1427736e64c3a8b513cd984332f596055a7ca196 (diff) | |
Merge tag 'tegra-for-5.2-bus' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/drivers
bus/tegra: Changes for v5.2-rc1
This pair of patches adds support for system sleep to the ACONNECT bus
found on Tegra SoCs.
* tag 'tegra-for-5.2-bus' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
bus: tegra-aconnect: add system sleep callbacks
bus: tegra-aconnect: use devm_clk_*() helpers
Signed-off-by: Olof Johansson <olof@lixom.net>
| -rw-r--r-- | drivers/bus/tegra-aconnect.c | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/drivers/bus/tegra-aconnect.c b/drivers/bus/tegra-aconnect.c index 084ae286fa23..ac58142301f4 100644 --- a/drivers/bus/tegra-aconnect.c +++ b/drivers/bus/tegra-aconnect.c | |||
| @@ -12,28 +12,38 @@ | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/of_platform.h> | 13 | #include <linux/of_platform.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/pm_clock.h> | ||
| 16 | #include <linux/pm_runtime.h> | 15 | #include <linux/pm_runtime.h> |
| 17 | 16 | ||
| 17 | struct tegra_aconnect { | ||
| 18 | struct clk *ape_clk; | ||
| 19 | struct clk *apb2ape_clk; | ||
| 20 | }; | ||
| 21 | |||
| 18 | static int tegra_aconnect_probe(struct platform_device *pdev) | 22 | static int tegra_aconnect_probe(struct platform_device *pdev) |
| 19 | { | 23 | { |
| 20 | int ret; | 24 | struct tegra_aconnect *aconnect; |
| 21 | 25 | ||
| 22 | if (!pdev->dev.of_node) | 26 | if (!pdev->dev.of_node) |
| 23 | return -EINVAL; | 27 | return -EINVAL; |
| 24 | 28 | ||
| 25 | ret = pm_clk_create(&pdev->dev); | 29 | aconnect = devm_kzalloc(&pdev->dev, sizeof(struct tegra_aconnect), |
| 26 | if (ret) | 30 | GFP_KERNEL); |
| 27 | return ret; | 31 | if (!aconnect) |
| 32 | return -ENOMEM; | ||
| 28 | 33 | ||
| 29 | ret = of_pm_clk_add_clk(&pdev->dev, "ape"); | 34 | aconnect->ape_clk = devm_clk_get(&pdev->dev, "ape"); |
| 30 | if (ret) | 35 | if (IS_ERR(aconnect->ape_clk)) { |
| 31 | goto clk_destroy; | 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"); | 40 | aconnect->apb2ape_clk = devm_clk_get(&pdev->dev, "apb2ape"); |
| 34 | if (ret) | 41 | if (IS_ERR(aconnect->apb2ape_clk)) { |
| 35 | goto clk_destroy; | 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 | pm_runtime_enable(&pdev->dev); | 47 | pm_runtime_enable(&pdev->dev); |
| 38 | 48 | ||
| 39 | of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); | 49 | of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); |
| @@ -41,35 +51,51 @@ static int tegra_aconnect_probe(struct platform_device *pdev) | |||
| 41 | dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n"); | 51 | dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n"); |
| 42 | 52 | ||
| 43 | return 0; | 53 | return 0; |
| 44 | |||
| 45 | clk_destroy: | ||
| 46 | pm_clk_destroy(&pdev->dev); | ||
| 47 | |||
| 48 | return ret; | ||
| 49 | } | 54 | } |
| 50 | 55 | ||
| 51 | static int tegra_aconnect_remove(struct platform_device *pdev) | 56 | static int tegra_aconnect_remove(struct platform_device *pdev) |
| 52 | { | 57 | { |
| 53 | pm_runtime_disable(&pdev->dev); | 58 | pm_runtime_disable(&pdev->dev); |
| 54 | 59 | ||
| 55 | pm_clk_destroy(&pdev->dev); | ||
| 56 | |||
| 57 | return 0; | 60 | return 0; |
| 58 | } | 61 | } |
| 59 | 62 | ||
| 60 | static int tegra_aconnect_runtime_resume(struct device *dev) | 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 | static int tegra_aconnect_runtime_suspend(struct device *dev) | 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 | static const struct dev_pm_ops tegra_aconnect_pm_ops = { | 94 | static const struct dev_pm_ops tegra_aconnect_pm_ops = { |
| 71 | SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend, | 95 | SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend, |
| 72 | tegra_aconnect_runtime_resume, NULL) | 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 | static const struct of_device_id tegra_aconnect_of_match[] = { | 101 | static const struct of_device_id tegra_aconnect_of_match[] = { |
