0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk-provider.h>
0009 #include <linux/device.h>
0010 #include <linux/err.h>
0011 #include <linux/of.h>
0012 #include <linux/module.h>
0013 #include <linux/scmi_protocol.h>
0014 #include <asm/div64.h>
0015
0016 static const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
0017
0018 struct scmi_clk {
0019 u32 id;
0020 struct clk_hw hw;
0021 const struct scmi_clock_info *info;
0022 const struct scmi_protocol_handle *ph;
0023 };
0024
0025 #define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
0026
0027 static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw,
0028 unsigned long parent_rate)
0029 {
0030 int ret;
0031 u64 rate;
0032 struct scmi_clk *clk = to_scmi_clk(hw);
0033
0034 ret = scmi_proto_clk_ops->rate_get(clk->ph, clk->id, &rate);
0035 if (ret)
0036 return 0;
0037 return rate;
0038 }
0039
0040 static long scmi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
0041 unsigned long *parent_rate)
0042 {
0043 u64 fmin, fmax, ftmp;
0044 struct scmi_clk *clk = to_scmi_clk(hw);
0045
0046
0047
0048
0049
0050
0051
0052 if (clk->info->rate_discrete)
0053 return rate;
0054
0055 fmin = clk->info->range.min_rate;
0056 fmax = clk->info->range.max_rate;
0057 if (rate <= fmin)
0058 return fmin;
0059 else if (rate >= fmax)
0060 return fmax;
0061
0062 ftmp = rate - fmin;
0063 ftmp += clk->info->range.step_size - 1;
0064 do_div(ftmp, clk->info->range.step_size);
0065
0066 return ftmp * clk->info->range.step_size + fmin;
0067 }
0068
0069 static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
0070 unsigned long parent_rate)
0071 {
0072 struct scmi_clk *clk = to_scmi_clk(hw);
0073
0074 return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate);
0075 }
0076
0077 static int scmi_clk_enable(struct clk_hw *hw)
0078 {
0079 struct scmi_clk *clk = to_scmi_clk(hw);
0080
0081 return scmi_proto_clk_ops->enable(clk->ph, clk->id);
0082 }
0083
0084 static void scmi_clk_disable(struct clk_hw *hw)
0085 {
0086 struct scmi_clk *clk = to_scmi_clk(hw);
0087
0088 scmi_proto_clk_ops->disable(clk->ph, clk->id);
0089 }
0090
0091 static int scmi_clk_atomic_enable(struct clk_hw *hw)
0092 {
0093 struct scmi_clk *clk = to_scmi_clk(hw);
0094
0095 return scmi_proto_clk_ops->enable_atomic(clk->ph, clk->id);
0096 }
0097
0098 static void scmi_clk_atomic_disable(struct clk_hw *hw)
0099 {
0100 struct scmi_clk *clk = to_scmi_clk(hw);
0101
0102 scmi_proto_clk_ops->disable_atomic(clk->ph, clk->id);
0103 }
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 static const struct clk_ops scmi_clk_ops = {
0119 .recalc_rate = scmi_clk_recalc_rate,
0120 .round_rate = scmi_clk_round_rate,
0121 .set_rate = scmi_clk_set_rate,
0122 .prepare = scmi_clk_enable,
0123 .unprepare = scmi_clk_disable,
0124 };
0125
0126 static const struct clk_ops scmi_atomic_clk_ops = {
0127 .recalc_rate = scmi_clk_recalc_rate,
0128 .round_rate = scmi_clk_round_rate,
0129 .set_rate = scmi_clk_set_rate,
0130 .enable = scmi_clk_atomic_enable,
0131 .disable = scmi_clk_atomic_disable,
0132 };
0133
0134 static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,
0135 const struct clk_ops *scmi_ops)
0136 {
0137 int ret;
0138 unsigned long min_rate, max_rate;
0139
0140 struct clk_init_data init = {
0141 .flags = CLK_GET_RATE_NOCACHE,
0142 .num_parents = 0,
0143 .ops = scmi_ops,
0144 .name = sclk->info->name,
0145 };
0146
0147 sclk->hw.init = &init;
0148 ret = devm_clk_hw_register(dev, &sclk->hw);
0149 if (ret)
0150 return ret;
0151
0152 if (sclk->info->rate_discrete) {
0153 int num_rates = sclk->info->list.num_rates;
0154
0155 if (num_rates <= 0)
0156 return -EINVAL;
0157
0158 min_rate = sclk->info->list.rates[0];
0159 max_rate = sclk->info->list.rates[num_rates - 1];
0160 } else {
0161 min_rate = sclk->info->range.min_rate;
0162 max_rate = sclk->info->range.max_rate;
0163 }
0164
0165 clk_hw_set_rate_range(&sclk->hw, min_rate, max_rate);
0166 return ret;
0167 }
0168
0169 static int scmi_clocks_probe(struct scmi_device *sdev)
0170 {
0171 int idx, count, err;
0172 unsigned int atomic_threshold;
0173 bool is_atomic;
0174 struct clk_hw **hws;
0175 struct clk_hw_onecell_data *clk_data;
0176 struct device *dev = &sdev->dev;
0177 struct device_node *np = dev->of_node;
0178 const struct scmi_handle *handle = sdev->handle;
0179 struct scmi_protocol_handle *ph;
0180
0181 if (!handle)
0182 return -ENODEV;
0183
0184 scmi_proto_clk_ops =
0185 handle->devm_protocol_get(sdev, SCMI_PROTOCOL_CLOCK, &ph);
0186 if (IS_ERR(scmi_proto_clk_ops))
0187 return PTR_ERR(scmi_proto_clk_ops);
0188
0189 count = scmi_proto_clk_ops->count_get(ph);
0190 if (count < 0) {
0191 dev_err(dev, "%pOFn: invalid clock output count\n", np);
0192 return -EINVAL;
0193 }
0194
0195 clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count),
0196 GFP_KERNEL);
0197 if (!clk_data)
0198 return -ENOMEM;
0199
0200 clk_data->num = count;
0201 hws = clk_data->hws;
0202
0203 is_atomic = handle->is_transport_atomic(handle, &atomic_threshold);
0204
0205 for (idx = 0; idx < count; idx++) {
0206 struct scmi_clk *sclk;
0207 const struct clk_ops *scmi_ops;
0208
0209 sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
0210 if (!sclk)
0211 return -ENOMEM;
0212
0213 sclk->info = scmi_proto_clk_ops->info_get(ph, idx);
0214 if (!sclk->info) {
0215 dev_dbg(dev, "invalid clock info for idx %d\n", idx);
0216 continue;
0217 }
0218
0219 sclk->id = idx;
0220 sclk->ph = ph;
0221
0222
0223
0224
0225
0226
0227 if (is_atomic &&
0228 sclk->info->enable_latency <= atomic_threshold)
0229 scmi_ops = &scmi_atomic_clk_ops;
0230 else
0231 scmi_ops = &scmi_clk_ops;
0232
0233 err = scmi_clk_ops_init(dev, sclk, scmi_ops);
0234 if (err) {
0235 dev_err(dev, "failed to register clock %d\n", idx);
0236 devm_kfree(dev, sclk);
0237 hws[idx] = NULL;
0238 } else {
0239 dev_dbg(dev, "Registered clock:%s%s\n",
0240 sclk->info->name,
0241 scmi_ops == &scmi_atomic_clk_ops ?
0242 " (atomic ops)" : "");
0243 hws[idx] = &sclk->hw;
0244 }
0245 }
0246
0247 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
0248 clk_data);
0249 }
0250
0251 static const struct scmi_device_id scmi_id_table[] = {
0252 { SCMI_PROTOCOL_CLOCK, "clocks" },
0253 { },
0254 };
0255 MODULE_DEVICE_TABLE(scmi, scmi_id_table);
0256
0257 static struct scmi_driver scmi_clocks_driver = {
0258 .name = "scmi-clocks",
0259 .probe = scmi_clocks_probe,
0260 .id_table = scmi_id_table,
0261 };
0262 module_scmi_driver(scmi_clocks_driver);
0263
0264 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
0265 MODULE_DESCRIPTION("ARM SCMI clock driver");
0266 MODULE_LICENSE("GPL v2");