File Index
Files and directories
Sign in
FILE

clk-scmi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/clk-scmi.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * System Control and Power Interface (SCMI) Protocol based clock driver
  4 *
  5 * Copyright (C) 2018-2024 ARM Ltd.
  6 */
  7
  8#include <linux/bits.h>
  9#include <linux/clk-provider.h>
 10#include <linux/device.h>
 11#include <linux/err.h>
 12#include <linux/of.h>
 13#include <linux/module.h>
 14#include <linux/scmi_protocol.h>
 15#include <asm/div64.h>
 16
 17#define NOT_ATOMIC	false
 18#define ATOMIC		true
 19
 20enum scmi_clk_feats {
 21	SCMI_CLK_ATOMIC_SUPPORTED,
 22	SCMI_CLK_STATE_CTRL_SUPPORTED,
 23	SCMI_CLK_RATE_CTRL_SUPPORTED,
 24	SCMI_CLK_PARENT_CTRL_SUPPORTED,
 25	SCMI_CLK_DUTY_CYCLE_SUPPORTED,
 26	SCMI_CLK_FEATS_COUNT
 27};
 28
 29#define SCMI_MAX_CLK_OPS	BIT(SCMI_CLK_FEATS_COUNT)
 30
 31static const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
 32
 33struct scmi_clk {
 34	u32 id;
 35	struct device *dev;
 36	struct clk_hw hw;
 37	const struct scmi_clock_info *info;
 38	const struct scmi_protocol_handle *ph;
 39	struct clk_parent_data *parent_data;
 40};
 41
 42#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
 43
 44static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw,
 45					  unsigned long parent_rate)
 46{
 47	int ret;
 48	u64 rate;
 49	struct scmi_clk *clk = to_scmi_clk(hw);
 50
 51	ret = scmi_proto_clk_ops->rate_get(clk->ph, clk->id, &rate);
 52	if (ret)
 53		return 0;
 54	return rate;
 55}
 56
 57static int scmi_clk_determine_rate(struct clk_hw *hw,
 58				   struct clk_rate_request *req)
 59{
 60	u64 fmin, fmax, ftmp;
 61	struct scmi_clk *clk = to_scmi_clk(hw);
 62
 63	/*
 64	 * We can't figure out what rate it will be, so just return the
 65	 * rate back to the caller. scmi_clk_recalc_rate() will be called
 66	 * after the rate is set and we'll know what rate the clock is
 67	 * running at then.
 68	 */
 69	if (clk->info->rate_discrete)
 70		return 0;
 71
 72	fmin = clk->info->range.min_rate;
 73	fmax = clk->info->range.max_rate;
 74	if (req->rate <= fmin) {
 75		req->rate = fmin;
 76
 77		return 0;
 78	} else if (req->rate >= fmax) {
 79		req->rate = fmax;
 80
 81		return 0;
 82	}
 83
 84	ftmp = req->rate - fmin;
 85	ftmp += clk->info->range.step_size - 1; /* to round up */
 86	do_div(ftmp, clk->info->range.step_size);
 87
 88	req->rate = ftmp * clk->info->range.step_size + fmin;
 89
 90	return 0;
 91}
 92
 93static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 94			     unsigned long parent_rate)
 95{
 96	struct scmi_clk *clk = to_scmi_clk(hw);
 97
 98	return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate);
 99}
100
101static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index)
102{
103	struct scmi_clk *clk = to_scmi_clk(hw);
104
105	return scmi_proto_clk_ops->parent_set(clk->ph, clk->id, parent_index);
106}
107
108static u8 scmi_clk_get_parent(struct clk_hw *hw)
109{
110	struct scmi_clk *clk = to_scmi_clk(hw);
111	u32 parent_id, p_idx;
112	int ret;
113
114	ret = scmi_proto_clk_ops->parent_get(clk->ph, clk->id, &parent_id);
115	if (ret)
116		return 0;
117
118	for (p_idx = 0; p_idx < clk->info->num_parents; p_idx++) {
119		if (clk->parent_data[p_idx].index == parent_id)
120			break;
121	}
122
123	if (p_idx == clk->info->num_parents)
124		return 0;
125
126	return p_idx;
127}
128
129static int scmi_clk_enable(struct clk_hw *hw)
130{
131	struct scmi_clk *clk = to_scmi_clk(hw);
132
133	return scmi_proto_clk_ops->enable(clk->ph, clk->id, NOT_ATOMIC);
134}
135
136static void scmi_clk_disable(struct clk_hw *hw)
137{
138	struct scmi_clk *clk = to_scmi_clk(hw);
139
140	scmi_proto_clk_ops->disable(clk->ph, clk->id, NOT_ATOMIC);
141}
142
143static int scmi_clk_atomic_enable(struct clk_hw *hw)
144{
145	struct scmi_clk *clk = to_scmi_clk(hw);
146
147	return scmi_proto_clk_ops->enable(clk->ph, clk->id, ATOMIC);
148}
149
150static void scmi_clk_atomic_disable(struct clk_hw *hw)
151{
152	struct scmi_clk *clk = to_scmi_clk(hw);
153
154	scmi_proto_clk_ops->disable(clk->ph, clk->id, ATOMIC);
155}
156
157static int __scmi_clk_is_enabled(struct clk_hw *hw, bool atomic)
158{
159	int ret;
160	bool enabled = false;
161	struct scmi_clk *clk = to_scmi_clk(hw);
162
163	ret = scmi_proto_clk_ops->state_get(clk->ph, clk->id, &enabled, atomic);
164	if (ret)
165		dev_warn(clk->dev,
166			 "Failed to get state for clock ID %d\n", clk->id);
167
168	return !!enabled;
169}
170
171static int scmi_clk_atomic_is_enabled(struct clk_hw *hw)
172{
173	return __scmi_clk_is_enabled(hw, ATOMIC);
174}
175
176static int scmi_clk_is_enabled(struct clk_hw *hw)
177{
178	return __scmi_clk_is_enabled(hw, NOT_ATOMIC);
179}
180
181static int scmi_clk_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty)
182{
183	int ret;
184	u32 val;
185	struct scmi_clk *clk = to_scmi_clk(hw);
186
187	ret = scmi_proto_clk_ops->config_oem_get(clk->ph, clk->id,
188						 SCMI_CLOCK_CFG_DUTY_CYCLE,
189						 &val, NULL, false);
190	if (!ret) {
191		duty->num = val;
192		duty->den = 100;
193	} else {
194		dev_warn(clk->dev,
195			 "Failed to get duty cycle for clock ID %d\n", clk->id);
196	}
197
198	return ret;
199}
200
201static int scmi_clk_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty)
202{
203	int ret;
204	u32 val;
205	struct scmi_clk *clk = to_scmi_clk(hw);
206
207	/* SCMI OEM Duty Cycle is expressed as a percentage */
208	val = (duty->num * 100) / duty->den;
209	ret = scmi_proto_clk_ops->config_oem_set(clk->ph, clk->id,
210						 SCMI_CLOCK_CFG_DUTY_CYCLE,
211						 val, false);
212	if (ret)
213		dev_warn(clk->dev,
214			 "Failed to set duty cycle(%u/%u) for clock ID %d\n",
215			 duty->num, duty->den, clk->id);
216
217	return ret;
218}
219
220static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,
221			     const struct clk_ops *scmi_ops)
222{
223	int ret;
224	unsigned long min_rate, max_rate;
225
226	struct clk_init_data init = {
227		.flags = CLK_GET_RATE_NOCACHE,
228		.num_parents = sclk->info->num_parents,
229		.ops = scmi_ops,
230		.name = sclk->info->name,
231		.parent_data = sclk->parent_data,
232	};
233
234	sclk->hw.init = &init;
235	ret = devm_clk_hw_register(dev, &sclk->hw);
236	if (ret)
237		return ret;
238
239	if (sclk->info->rate_discrete) {
240		int num_rates = sclk->info->list.num_rates;
241
242		if (num_rates <= 0)
243			return -EINVAL;
244
245		min_rate = sclk->info->list.rates[0];
246		max_rate = sclk->info->list.rates[num_rates - 1];
247	} else {
248		min_rate = sclk->info->range.min_rate;
249		max_rate = sclk->info->range.max_rate;
250	}
251
252	clk_hw_set_rate_range(&sclk->hw, min_rate, max_rate);
253	return ret;
254}
255
256/**
257 * scmi_clk_ops_alloc() - Alloc and configure clock operations
258 * @dev: A device reference for devres
259 * @feats_key: A bitmap representing the desired clk_ops capabilities
260 *
261 * Allocate and configure a proper set of clock operations depending on the
262 * specifically required SCMI clock features.
263 *
264 * Return: A pointer to the allocated and configured clk_ops on success,
265 *	   or NULL on allocation failure.
266 */
267static const struct clk_ops *
268scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key)
269{
270	struct clk_ops *ops;
271
272	ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL);
273	if (!ops)
274		return NULL;
275	/*
276	 * We can provide enable/disable/is_enabled atomic callbacks only if the
277	 * underlying SCMI transport for an SCMI instance is configured to
278	 * handle SCMI commands in an atomic manner.
279	 *
280	 * When no SCMI atomic transport support is available we instead provide
281	 * only the prepare/unprepare API, as allowed by the clock framework
282	 * when atomic calls are not available.
283	 */
284	if (feats_key & BIT(SCMI_CLK_STATE_CTRL_SUPPORTED)) {
285		if (feats_key & BIT(SCMI_CLK_ATOMIC_SUPPORTED)) {
286			ops->enable = scmi_clk_atomic_enable;
287			ops->disable = scmi_clk_atomic_disable;
288		} else {
289			ops->prepare = scmi_clk_enable;
290			ops->unprepare = scmi_clk_disable;
291		}
292	}
293
294	if (feats_key & BIT(SCMI_CLK_ATOMIC_SUPPORTED))
295		ops->is_enabled = scmi_clk_atomic_is_enabled;
296	else
297		ops->is_prepared = scmi_clk_is_enabled;
298
299	/* Rate ops */
300	ops->recalc_rate = scmi_clk_recalc_rate;
301	ops->determine_rate = scmi_clk_determine_rate;
302	if (feats_key & BIT(SCMI_CLK_RATE_CTRL_SUPPORTED))
303		ops->set_rate = scmi_clk_set_rate;
304
305	/* Parent ops */
306	ops->get_parent = scmi_clk_get_parent;
307	if (feats_key & BIT(SCMI_CLK_PARENT_CTRL_SUPPORTED))
308		ops->set_parent = scmi_clk_set_parent;
309
310	/* Duty cycle */
311	if (feats_key & BIT(SCMI_CLK_DUTY_CYCLE_SUPPORTED)) {
312		ops->get_duty_cycle = scmi_clk_get_duty_cycle;
313		ops->set_duty_cycle = scmi_clk_set_duty_cycle;
314	}
315
316	return ops;
317}
318
319/**
320 * scmi_clk_ops_select() - Select a proper set of clock operations
321 * @sclk: A reference to an SCMI clock descriptor
322 * @atomic_capable: A flag to indicate if atomic mode is supported by the
323 *		    transport
324 * @atomic_threshold_us: Platform atomic threshold value in microseconds:
325 *			 clk_ops are atomic when clock enable latency is less
326 *			 than this threshold
327 * @clk_ops_db: A reference to the array used as a database to store all the
328 *		created clock operations combinations.
329 * @db_size: Maximum number of entries held by @clk_ops_db
330 *
331 * After having built a bitmap descriptor to represent the set of features
332 * needed by this SCMI clock, at first use it to lookup into the set of
333 * previously allocated clk_ops to check if a suitable combination of clock
334 * operations was already created; when no match is found allocate a brand new
335 * set of clk_ops satisfying the required combination of features and save it
336 * for future references.
337 *
338 * In this way only one set of clk_ops is ever created for each different
339 * combination that is effectively needed by a driver instance.
340 *
341 * Return: A pointer to the allocated and configured clk_ops on success, or
342 *	   NULL otherwise.
343 */
344static const struct clk_ops *
345scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
346		    unsigned int atomic_threshold_us,
347		    const struct clk_ops **clk_ops_db, size_t db_size)
348{
349	int ret;
350	u32 val;
351	const struct scmi_clock_info *ci = sclk->info;
352	unsigned int feats_key = 0;
353	const struct clk_ops *ops;
354
355	/*
356	 * Note that when transport is atomic but SCMI protocol did not
357	 * specify (or support) an enable_latency associated with a
358	 * clock, we default to use atomic operations mode.
359	 */
360	if (atomic_capable && ci->enable_latency <= atomic_threshold_us)
361		feats_key |= BIT(SCMI_CLK_ATOMIC_SUPPORTED);
362
363	if (!ci->state_ctrl_forbidden)
364		feats_key |= BIT(SCMI_CLK_STATE_CTRL_SUPPORTED);
365
366	if (!ci->rate_ctrl_forbidden)
367		feats_key |= BIT(SCMI_CLK_RATE_CTRL_SUPPORTED);
368
369	if (!ci->parent_ctrl_forbidden)
370		feats_key |= BIT(SCMI_CLK_PARENT_CTRL_SUPPORTED);
371
372	if (ci->extended_config) {
373		ret = scmi_proto_clk_ops->config_oem_get(sclk->ph, sclk->id,
374						 SCMI_CLOCK_CFG_DUTY_CYCLE,
375						 &val, NULL, false);
376		if (!ret)
377			feats_key |= BIT(SCMI_CLK_DUTY_CYCLE_SUPPORTED);
378	}
379
380	if (WARN_ON(feats_key >= db_size))
381		return NULL;
382
383	/* Lookup previously allocated ops */
384	ops = clk_ops_db[feats_key];
385	if (ops)
386		return ops;
387
388	/* Did not find a pre-allocated clock_ops */
389	ops = scmi_clk_ops_alloc(sclk->dev, feats_key);
390	if (!ops)
391		return NULL;
392
393	/* Store new ops combinations */
394	clk_ops_db[feats_key] = ops;
395
396	return ops;
397}
398
399static int scmi_clocks_probe(struct scmi_device *sdev)
400{
401	int idx, count, err;
402	unsigned int atomic_threshold_us;
403	bool transport_is_atomic;
404	struct clk_hw **hws;
405	struct clk_hw_onecell_data *clk_data;
406	struct device *dev = &sdev->dev;
407	struct device_node *np = dev->of_node;
408	const struct scmi_handle *handle = sdev->handle;
409	struct scmi_protocol_handle *ph;
410	const struct clk_ops *scmi_clk_ops_db[SCMI_MAX_CLK_OPS] = {};
411	struct scmi_clk *sclks;
412
413	if (!handle)
414		return -ENODEV;
415
416	scmi_proto_clk_ops =
417		handle->devm_protocol_get(sdev, SCMI_PROTOCOL_CLOCK, &ph);
418	if (IS_ERR(scmi_proto_clk_ops))
419		return PTR_ERR(scmi_proto_clk_ops);
420
421	count = scmi_proto_clk_ops->count_get(ph);
422	if (count < 0) {
423		dev_err(dev, "%pOFn: invalid clock output count\n", np);
424		return -EINVAL;
425	}
426
427	clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count),
428				GFP_KERNEL);
429	if (!clk_data)
430		return -ENOMEM;
431
432	clk_data->num = count;
433	hws = clk_data->hws;
434
435	transport_is_atomic = handle->is_transport_atomic(handle,
436							  &atomic_threshold_us);
437
438	sclks = devm_kcalloc(dev, count, sizeof(*sclks), GFP_KERNEL);
439	if (!sclks)
440		return -ENOMEM;
441
442	for (idx = 0; idx < count; idx++)
443		hws[idx] = &sclks[idx].hw;
444
445	for (idx = 0; idx < count; idx++) {
446		struct scmi_clk *sclk = &sclks[idx];
447		const struct clk_ops *scmi_ops;
448
449		sclk->info = scmi_proto_clk_ops->info_get(ph, idx);
450		if (!sclk->info) {
451			dev_dbg(dev, "invalid clock info for idx %d\n", idx);
452			hws[idx] = NULL;
453			continue;
454		}
455
456		sclk->id = idx;
457		sclk->ph = ph;
458		sclk->dev = dev;
459
460		/*
461		 * Note that the scmi_clk_ops_db is on the stack, not global,
462		 * because it cannot be shared between multiple probe-sequences
463		 * to avoid sharing the devm_ allocated clk_ops between multiple
464		 * SCMI clk driver instances.
465		 */
466		scmi_ops = scmi_clk_ops_select(sclk, transport_is_atomic,
467					       atomic_threshold_us,
468					       scmi_clk_ops_db,
469					       ARRAY_SIZE(scmi_clk_ops_db));
470		if (!scmi_ops)
471			return -ENOMEM;
472
473		/* Initialize clock parent data. */
474		if (sclk->info->num_parents > 0) {
475			sclk->parent_data = devm_kcalloc(dev, sclk->info->num_parents,
476							 sizeof(*sclk->parent_data), GFP_KERNEL);
477			if (!sclk->parent_data)
478				return -ENOMEM;
479
480			for (int i = 0; i < sclk->info->num_parents; i++) {
481				sclk->parent_data[i].index = sclk->info->parents[i];
482				sclk->parent_data[i].hw = hws[sclk->info->parents[i]];
483			}
484		}
485
486		err = scmi_clk_ops_init(dev, sclk, scmi_ops);
487		if (err) {
488			dev_err(dev, "failed to register clock %d\n", idx);
489			devm_kfree(dev, sclk->parent_data);
490			hws[idx] = NULL;
491		} else {
492			dev_dbg(dev, "Registered clock:%s%s\n",
493				sclk->info->name,
494				scmi_ops->enable ? " (atomic ops)" : "");
495		}
496	}
497
498	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
499					   clk_data);
500}
501
502static const struct scmi_device_id scmi_id_table[] = {
503	{ SCMI_PROTOCOL_CLOCK, "clocks" },
504	{ },
505};
506MODULE_DEVICE_TABLE(scmi, scmi_id_table);
507
508static struct scmi_driver scmi_clocks_driver = {
509	.name = "scmi-clocks",
510	.probe = scmi_clocks_probe,
511	.id_table = scmi_id_table,
512};
513module_scmi_driver(scmi_clocks_driver);
514
515MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
516MODULE_DESCRIPTION("ARM SCMI clock driver");
517MODULE_LICENSE("GPL v2");
~/ Read-only file preview.