Commit | Line | Data |
---|---|---|
46a88534 JH |
1 | /* |
2 | * Tegra ACONNECT Bus Driver | |
3 | * | |
4 | * Copyright (C) 2016, NVIDIA CORPORATION. All rights reserved. | |
5 | * | |
6 | * This file is subject to the terms and conditions of the GNU General Public | |
7 | * License. See the file "COPYING" in the main directory of this archive | |
8 | * for more details. | |
9 | */ | |
10 | ||
11 | #include <linux/clk.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/of_platform.h> | |
14 | #include <linux/platform_device.h> | |
15 | #include <linux/pm_clock.h> | |
16 | #include <linux/pm_runtime.h> | |
17 | ||
18 | static int tegra_aconnect_add_clock(struct device *dev, char *name) | |
19 | { | |
20 | struct clk *clk; | |
21 | int ret; | |
22 | ||
23 | clk = clk_get(dev, name); | |
24 | if (IS_ERR(clk)) { | |
25 | dev_err(dev, "%s clock not found\n", name); | |
26 | return PTR_ERR(clk); | |
27 | } | |
28 | ||
29 | ret = pm_clk_add_clk(dev, clk); | |
30 | if (ret) | |
31 | clk_put(clk); | |
32 | ||
33 | return ret; | |
34 | } | |
35 | ||
36 | static int tegra_aconnect_probe(struct platform_device *pdev) | |
37 | { | |
38 | int ret; | |
39 | ||
40 | if (!pdev->dev.of_node) | |
41 | return -EINVAL; | |
42 | ||
43 | ret = pm_clk_create(&pdev->dev); | |
44 | if (ret) | |
45 | return ret; | |
46 | ||
47 | ret = tegra_aconnect_add_clock(&pdev->dev, "ape"); | |
48 | if (ret) | |
49 | goto clk_destroy; | |
50 | ||
51 | ret = tegra_aconnect_add_clock(&pdev->dev, "apb2ape"); | |
52 | if (ret) | |
53 | goto clk_destroy; | |
54 | ||
55 | pm_runtime_enable(&pdev->dev); | |
56 | ||
57 | of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); | |
58 | ||
59 | dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n"); | |
60 | ||
61 | return 0; | |
62 | ||
63 | clk_destroy: | |
64 | pm_clk_destroy(&pdev->dev); | |
65 | ||
66 | return ret; | |
67 | } | |
68 | ||
69 | static int tegra_aconnect_remove(struct platform_device *pdev) | |
70 | { | |
71 | pm_runtime_disable(&pdev->dev); | |
72 | ||
73 | pm_clk_destroy(&pdev->dev); | |
74 | ||
75 | return 0; | |
76 | } | |
77 | ||
78 | static int tegra_aconnect_runtime_resume(struct device *dev) | |
79 | { | |
80 | return pm_clk_resume(dev); | |
81 | } | |
82 | ||
83 | static int tegra_aconnect_runtime_suspend(struct device *dev) | |
84 | { | |
85 | return pm_clk_suspend(dev); | |
86 | } | |
87 | ||
88 | static const struct dev_pm_ops tegra_aconnect_pm_ops = { | |
89 | SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend, | |
90 | tegra_aconnect_runtime_resume, NULL) | |
91 | }; | |
92 | ||
93 | static const struct of_device_id tegra_aconnect_of_match[] = { | |
94 | { .compatible = "nvidia,tegra210-aconnect", }, | |
95 | { } | |
96 | }; | |
97 | MODULE_DEVICE_TABLE(of, tegra_aconnect_of_match); | |
98 | ||
99 | static struct platform_driver tegra_aconnect_driver = { | |
100 | .probe = tegra_aconnect_probe, | |
101 | .remove = tegra_aconnect_remove, | |
102 | .driver = { | |
103 | .name = "tegra-aconnect", | |
104 | .of_match_table = tegra_aconnect_of_match, | |
105 | .pm = &tegra_aconnect_pm_ops, | |
106 | }, | |
107 | }; | |
108 | module_platform_driver(tegra_aconnect_driver); | |
109 | ||
110 | MODULE_DESCRIPTION("NVIDIA Tegra ACONNECT Bus Driver"); | |
111 | MODULE_AUTHOR("Jon Hunter <jonathanh@nvidia.com>"); | |
112 | MODULE_LICENSE("GPL v2"); |