1 // SPDX-License-Identifier: GPL-2.0-only
2
3 #include <linux/clk.h>
4 #include <linux/clk-provider.h>
5 #include <linux/mutex.h>
6 #include <linux/platform_device.h>
7 #include <linux/pm_domain.h>
8 #include <linux/pm_opp.h>
9 #include <linux/pm_runtime.h>
10 #include <linux/slab.h>
11
12 #include <soc/tegra/common.h>
13
14 #include "clk.h"
15
16 /*
17 * This driver manages performance state of the core power domain for the
18 * independent PLLs and system clocks. We created a virtual clock device
19 * for such clocks, see tegra_clk_dev_register().
20 */
21
22 struct tegra_clk_device {
23 struct notifier_block clk_nb;
24 struct device *dev;
25 struct clk_hw *hw;
26 struct mutex lock;
27 };
28
tegra_clock_set_pd_state(struct tegra_clk_device * clk_dev,unsigned long rate)29 static int tegra_clock_set_pd_state(struct tegra_clk_device *clk_dev,
30 unsigned long rate)
31 {
32 struct device *dev = clk_dev->dev;
33 struct dev_pm_opp *opp;
34 unsigned int pstate;
35
36 opp = dev_pm_opp_find_freq_ceil(dev, &rate);
37 if (opp == ERR_PTR(-ERANGE)) {
38 /*
39 * Some clocks may be unused by a particular board and they
40 * may have uninitiated clock rate that is overly high. In
41 * this case clock is expected to be disabled, but still we
42 * need to set up performance state of the power domain and
43 * not error out clk initialization. A typical example is
44 * a PCIe clock on Android tablets.
45 */
46 dev_dbg(dev, "failed to find ceil OPP for %luHz\n", rate);
47 opp = dev_pm_opp_find_freq_floor(dev, &rate);
48 }
49
50 if (IS_ERR(opp)) {
51 dev_err(dev, "failed to find OPP for %luHz: %pe\n", rate, opp);
52 return PTR_ERR(opp);
53 }
54
55 pstate = dev_pm_opp_get_required_pstate(opp, 0);
56 dev_pm_opp_put(opp);
57
58 return dev_pm_genpd_set_performance_state(dev, pstate);
59 }
60
tegra_clock_change_notify(struct notifier_block * nb,unsigned long msg,void * data)61 static int tegra_clock_change_notify(struct notifier_block *nb,
62 unsigned long msg, void *data)
63 {
64 struct clk_notifier_data *cnd = data;
65 struct tegra_clk_device *clk_dev;
66 int err = 0;
67
68 clk_dev = container_of(nb, struct tegra_clk_device, clk_nb);
69
70 mutex_lock(&clk_dev->lock);
71 switch (msg) {
72 case PRE_RATE_CHANGE:
73 if (cnd->new_rate > cnd->old_rate)
74 err = tegra_clock_set_pd_state(clk_dev, cnd->new_rate);
75 break;
76
77 case ABORT_RATE_CHANGE:
78 err = tegra_clock_set_pd_state(clk_dev, cnd->old_rate);
79 break;
80
81 case POST_RATE_CHANGE:
82 if (cnd->new_rate < cnd->old_rate)
83 err = tegra_clock_set_pd_state(clk_dev, cnd->new_rate);
84 break;
85
86 default:
87 break;
88 }
89 mutex_unlock(&clk_dev->lock);
90
91 return notifier_from_errno(err);
92 }
93
tegra_clock_sync_pd_state(struct tegra_clk_device * clk_dev)94 static int tegra_clock_sync_pd_state(struct tegra_clk_device *clk_dev)
95 {
96 unsigned long rate;
97 int ret;
98
99 mutex_lock(&clk_dev->lock);
100
101 rate = clk_hw_get_rate(clk_dev->hw);
102 ret = tegra_clock_set_pd_state(clk_dev, rate);
103
104 mutex_unlock(&clk_dev->lock);
105
106 return ret;
107 }
108
tegra_clock_probe(struct platform_device * pdev)109 static int tegra_clock_probe(struct platform_device *pdev)
110 {
111 struct tegra_core_opp_params opp_params = {};
112 struct tegra_clk_device *clk_dev;
113 struct device *dev = &pdev->dev;
114 struct clk *clk;
115 int err;
116
117 if (!dev->pm_domain)
118 return -EINVAL;
119
120 clk_dev = devm_kzalloc(dev, sizeof(*clk_dev), GFP_KERNEL);
121 if (!clk_dev)
122 return -ENOMEM;
123
124 clk = devm_clk_get(dev, NULL);
125 if (IS_ERR(clk))
126 return PTR_ERR(clk);
127
128 clk_dev->dev = dev;
129 clk_dev->hw = __clk_get_hw(clk);
130 clk_dev->clk_nb.notifier_call = tegra_clock_change_notify;
131 mutex_init(&clk_dev->lock);
132
133 platform_set_drvdata(pdev, clk_dev);
134
135 /*
136 * Runtime PM was already enabled for this device by the parent clk
137 * driver and power domain state should be synced under clk_dev lock,
138 * hence we don't use the common OPP helper that initializes OPP
139 * state. For some clocks common OPP helper may fail to find ceil
140 * rate, it's handled by this driver.
141 */
142 err = devm_tegra_core_dev_init_opp_table(dev, &opp_params);
143 if (err)
144 return err;
145
146 err = clk_notifier_register(clk, &clk_dev->clk_nb);
147 if (err) {
148 dev_err(dev, "failed to register clk notifier: %d\n", err);
149 return err;
150 }
151
152 /*
153 * The driver is attaching to a potentially active/resumed clock, hence
154 * we need to sync the power domain performance state in a accordance to
155 * the clock rate if clock is resumed.
156 */
157 err = tegra_clock_sync_pd_state(clk_dev);
158 if (err)
159 goto unreg_clk;
160
161 return 0;
162
163 unreg_clk:
164 clk_notifier_unregister(clk, &clk_dev->clk_nb);
165
166 return err;
167 }
168
169 /*
170 * Tegra GENPD driver enables clocks during NOIRQ phase. It can't be done
171 * for clocks served by this driver because runtime PM is unavailable in
172 * NOIRQ phase. We will keep clocks resumed during suspend to mitigate this
173 * problem. In practice this makes no difference from a power management
174 * perspective since voltage is kept at a nominal level during suspend anyways.
175 */
tegra_clock_suspend(struct device * dev)176 static inline int tegra_clock_suspend(struct device *dev)
177 {
178 int ret;
179
180 ret = pm_runtime_resume(dev);
181 if (ret < 0)
182 return ret;
183
184 return 0;
185 }
186
187 static const struct dev_pm_ops tegra_clock_pm = {
188 SET_SYSTEM_SLEEP_PM_OPS(tegra_clock_suspend, NULL)
189 };
190
191 static const struct of_device_id tegra_clock_match[] = {
192 { .compatible = "nvidia,tegra20-sclk" },
193 { .compatible = "nvidia,tegra30-sclk" },
194 { .compatible = "nvidia,tegra30-pllc" },
195 { .compatible = "nvidia,tegra30-plle" },
196 { .compatible = "nvidia,tegra30-pllm" },
197 { }
198 };
199
200 static struct platform_driver tegra_clock_driver = {
201 .driver = {
202 .name = "tegra-clock",
203 .of_match_table = tegra_clock_match,
204 .pm = &tegra_clock_pm,
205 .suppress_bind_attrs = true,
206 },
207 .probe = tegra_clock_probe,
208 };
209 builtin_platform_driver(tegra_clock_driver);
210