.. | .. |
---|
2 | 2 | /* |
---|
3 | 3 | * System Control and Power Interface (SCMI) Protocol based clock driver |
---|
4 | 4 | * |
---|
5 | | - * Copyright (C) 2018 ARM Ltd. |
---|
| 5 | + * Copyright (C) 2018-2020 ARM Ltd. |
---|
6 | 6 | */ |
---|
7 | 7 | |
---|
8 | 8 | #include <linux/clk-provider.h> |
---|
.. | .. |
---|
13 | 13 | #include <linux/scmi_protocol.h> |
---|
14 | 14 | #include <asm/div64.h> |
---|
15 | 15 | |
---|
| 16 | +static const struct scmi_clk_proto_ops *clk_ops; |
---|
| 17 | + |
---|
16 | 18 | struct scmi_clk { |
---|
17 | 19 | u32 id; |
---|
18 | 20 | struct clk_hw hw; |
---|
19 | 21 | const struct scmi_clock_info *info; |
---|
20 | | - const struct scmi_handle *handle; |
---|
| 22 | + const struct scmi_protocol_handle *ph; |
---|
21 | 23 | }; |
---|
22 | 24 | |
---|
23 | 25 | #define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw) |
---|
.. | .. |
---|
29 | 31 | u64 rate; |
---|
30 | 32 | struct scmi_clk *clk = to_scmi_clk(hw); |
---|
31 | 33 | |
---|
32 | | - ret = clk->handle->clk_ops->rate_get(clk->handle, clk->id, &rate); |
---|
| 34 | + ret = clk_ops->rate_get(clk->ph, clk->id, &rate); |
---|
33 | 35 | if (ret) |
---|
34 | 36 | return 0; |
---|
35 | 37 | return rate; |
---|
.. | .. |
---|
69 | 71 | { |
---|
70 | 72 | struct scmi_clk *clk = to_scmi_clk(hw); |
---|
71 | 73 | |
---|
72 | | - return clk->handle->clk_ops->rate_set(clk->handle, clk->id, rate); |
---|
| 74 | + return clk_ops->rate_set(clk->ph, clk->id, rate); |
---|
73 | 75 | } |
---|
74 | 76 | |
---|
75 | 77 | static int scmi_clk_enable(struct clk_hw *hw) |
---|
76 | 78 | { |
---|
77 | 79 | struct scmi_clk *clk = to_scmi_clk(hw); |
---|
78 | 80 | |
---|
79 | | - return clk->handle->clk_ops->enable(clk->handle, clk->id); |
---|
| 81 | + return clk_ops->enable(clk->ph, clk->id); |
---|
80 | 82 | } |
---|
81 | 83 | |
---|
82 | 84 | static void scmi_clk_disable(struct clk_hw *hw) |
---|
83 | 85 | { |
---|
84 | 86 | struct scmi_clk *clk = to_scmi_clk(hw); |
---|
85 | 87 | |
---|
86 | | - clk->handle->clk_ops->disable(clk->handle, clk->id); |
---|
| 88 | + clk_ops->disable(clk->ph, clk->id); |
---|
87 | 89 | } |
---|
88 | 90 | |
---|
89 | 91 | static const struct clk_ops scmi_clk_ops = { |
---|
.. | .. |
---|
142 | 144 | struct device *dev = &sdev->dev; |
---|
143 | 145 | struct device_node *np = dev->of_node; |
---|
144 | 146 | const struct scmi_handle *handle = sdev->handle; |
---|
| 147 | + struct scmi_protocol_handle *ph; |
---|
145 | 148 | |
---|
146 | | - if (!handle || !handle->clk_ops) |
---|
| 149 | + if (!handle) |
---|
147 | 150 | return -ENODEV; |
---|
148 | 151 | |
---|
149 | | - count = handle->clk_ops->count_get(handle); |
---|
| 152 | + clk_ops = handle->devm_get_protocol(sdev, SCMI_PROTOCOL_CLOCK, &ph); |
---|
| 153 | + if (IS_ERR(clk_ops)) |
---|
| 154 | + return PTR_ERR(clk_ops); |
---|
| 155 | + |
---|
| 156 | + count = clk_ops->count_get(ph); |
---|
150 | 157 | if (count < 0) { |
---|
151 | | - dev_err(dev, "%s: invalid clock output count\n", np->name); |
---|
| 158 | + dev_err(dev, "%pOFn: invalid clock output count\n", np); |
---|
152 | 159 | return -EINVAL; |
---|
153 | 160 | } |
---|
154 | 161 | |
---|
.. | .. |
---|
167 | 174 | if (!sclk) |
---|
168 | 175 | return -ENOMEM; |
---|
169 | 176 | |
---|
170 | | - sclk->info = handle->clk_ops->info_get(handle, idx); |
---|
| 177 | + sclk->info = clk_ops->info_get(ph, idx); |
---|
171 | 178 | if (!sclk->info) { |
---|
172 | 179 | dev_dbg(dev, "invalid clock info for idx %d\n", idx); |
---|
173 | 180 | continue; |
---|
174 | 181 | } |
---|
175 | 182 | |
---|
176 | 183 | sclk->id = idx; |
---|
177 | | - sclk->handle = handle; |
---|
| 184 | + sclk->ph = ph; |
---|
178 | 185 | |
---|
179 | 186 | err = scmi_clk_ops_init(dev, sclk); |
---|
180 | 187 | if (err) { |
---|
.. | .. |
---|
192 | 199 | } |
---|
193 | 200 | |
---|
194 | 201 | static const struct scmi_device_id scmi_id_table[] = { |
---|
195 | | - { SCMI_PROTOCOL_CLOCK }, |
---|
| 202 | + { SCMI_PROTOCOL_CLOCK, "clocks" }, |
---|
196 | 203 | { }, |
---|
197 | 204 | }; |
---|
198 | 205 | MODULE_DEVICE_TABLE(scmi, scmi_id_table); |
---|
.. | .. |
---|
202 | 209 | .probe = scmi_clocks_probe, |
---|
203 | 210 | .id_table = scmi_id_table, |
---|
204 | 211 | }; |
---|
205 | | -#ifdef CONFIG_ARCH_ROCKCHIP |
---|
206 | | -static int __init scmi_clocks_driver_init(void) |
---|
207 | | -{ |
---|
208 | | - return scmi_register(&scmi_clocks_driver); |
---|
209 | | -} |
---|
210 | | -subsys_initcall_sync(scmi_clocks_driver_init); |
---|
211 | | - |
---|
212 | | -static void __exit scmi_clocks_driver_exit(void) |
---|
213 | | -{ |
---|
214 | | - scmi_unregister(&scmi_clocks_driver); |
---|
215 | | -} |
---|
216 | | -module_exit(scmi_clocks_driver_exit); |
---|
217 | | -#else |
---|
218 | 212 | module_scmi_driver(scmi_clocks_driver); |
---|
219 | | -#endif |
---|
220 | 213 | |
---|
221 | 214 | MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>"); |
---|
222 | 215 | MODULE_DESCRIPTION("ARM SCMI clock driver"); |
---|