| .. | .. |
|---|
| 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"); |
|---|