xref: /openbmc/linux/drivers/clk/tegra/clk-bpmp.c (revision 3d92aa45)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2016 NVIDIA Corporation
4  */
5 
6 #include <linux/clk-provider.h>
7 #include <linux/device.h>
8 #include <linux/seq_buf.h>
9 #include <linux/slab.h>
10 
11 #include <soc/tegra/bpmp.h>
12 #include <soc/tegra/bpmp-abi.h>
13 
14 #define TEGRA_BPMP_DUMP_CLOCK_INFO	0
15 
16 #define TEGRA_BPMP_CLK_HAS_MUX		BIT(0)
17 #define TEGRA_BPMP_CLK_HAS_SET_RATE	BIT(1)
18 #define TEGRA_BPMP_CLK_IS_ROOT		BIT(2)
19 
20 struct tegra_bpmp_clk_info {
21 	unsigned int id;
22 	char name[MRQ_CLK_NAME_MAXLEN];
23 	unsigned int parents[MRQ_CLK_MAX_PARENTS];
24 	unsigned int num_parents;
25 	unsigned long flags;
26 };
27 
28 struct tegra_bpmp_clk {
29 	struct clk_hw hw;
30 
31 	struct tegra_bpmp *bpmp;
32 	unsigned int id;
33 
34 	unsigned int num_parents;
35 	unsigned int *parents;
36 };
37 
38 static inline struct tegra_bpmp_clk *to_tegra_bpmp_clk(struct clk_hw *hw)
39 {
40 	return container_of(hw, struct tegra_bpmp_clk, hw);
41 }
42 
43 struct tegra_bpmp_clk_message {
44 	unsigned int cmd;
45 	unsigned int id;
46 
47 	struct {
48 		const void *data;
49 		size_t size;
50 	} tx;
51 
52 	struct {
53 		void *data;
54 		size_t size;
55 		int ret;
56 	} rx;
57 };
58 
59 static int tegra_bpmp_clk_transfer(struct tegra_bpmp *bpmp,
60 				   const struct tegra_bpmp_clk_message *clk)
61 {
62 	struct mrq_clk_request request;
63 	struct tegra_bpmp_message msg;
64 	void *req = &request;
65 	int err;
66 
67 	memset(&request, 0, sizeof(request));
68 	request.cmd_and_id = (clk->cmd << 24) | clk->id;
69 
70 	/*
71 	 * The mrq_clk_request structure has an anonymous union at offset 4
72 	 * that contains all possible sub-command structures. Copy the data
73 	 * to that union. Ideally we'd be able to refer to it by name, but
74 	 * doing so would require changing the ABI header and increase the
75 	 * maintenance burden.
76 	 */
77 	memcpy(req + 4, clk->tx.data, clk->tx.size);
78 
79 	memset(&msg, 0, sizeof(msg));
80 	msg.mrq = MRQ_CLK;
81 	msg.tx.data = &request;
82 	msg.tx.size = sizeof(request);
83 	msg.rx.data = clk->rx.data;
84 	msg.rx.size = clk->rx.size;
85 
86 	err = tegra_bpmp_transfer(bpmp, &msg);
87 	if (err < 0)
88 		return err;
89 	else if (msg.rx.ret < 0)
90 		return -EINVAL;
91 
92 	return 0;
93 }
94 
95 static int tegra_bpmp_clk_prepare(struct clk_hw *hw)
96 {
97 	struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
98 	struct tegra_bpmp_clk_message msg;
99 
100 	memset(&msg, 0, sizeof(msg));
101 	msg.cmd = CMD_CLK_ENABLE;
102 	msg.id = clk->id;
103 
104 	return tegra_bpmp_clk_transfer(clk->bpmp, &msg);
105 }
106 
107 static void tegra_bpmp_clk_unprepare(struct clk_hw *hw)
108 {
109 	struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
110 	struct tegra_bpmp_clk_message msg;
111 	int err;
112 
113 	memset(&msg, 0, sizeof(msg));
114 	msg.cmd = CMD_CLK_DISABLE;
115 	msg.id = clk->id;
116 
117 	err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
118 	if (err < 0)
119 		dev_err(clk->bpmp->dev, "failed to disable clock %s: %d\n",
120 			clk_hw_get_name(hw), err);
121 }
122 
123 static int tegra_bpmp_clk_is_prepared(struct clk_hw *hw)
124 {
125 	struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
126 	struct cmd_clk_is_enabled_response response;
127 	struct tegra_bpmp_clk_message msg;
128 	int err;
129 
130 	memset(&msg, 0, sizeof(msg));
131 	msg.cmd = CMD_CLK_IS_ENABLED;
132 	msg.id = clk->id;
133 	msg.rx.data = &response;
134 	msg.rx.size = sizeof(response);
135 
136 	err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
137 	if (err < 0)
138 		return err;
139 
140 	return response.state;
141 }
142 
143 static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw *hw,
144 						unsigned long parent_rate)
145 {
146 	struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
147 	struct cmd_clk_get_rate_response response;
148 	struct cmd_clk_get_rate_request request;
149 	struct tegra_bpmp_clk_message msg;
150 	int err;
151 
152 	memset(&msg, 0, sizeof(msg));
153 	msg.cmd = CMD_CLK_GET_RATE;
154 	msg.id = clk->id;
155 	msg.tx.data = &request;
156 	msg.tx.size = sizeof(request);
157 	msg.rx.data = &response;
158 	msg.rx.size = sizeof(response);
159 
160 	err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
161 	if (err < 0)
162 		return err;
163 
164 	return response.rate;
165 }
166 
167 static long tegra_bpmp_clk_round_rate(struct clk_hw *hw, unsigned long rate,
168 				      unsigned long *parent_rate)
169 {
170 	struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
171 	struct cmd_clk_round_rate_response response;
172 	struct cmd_clk_round_rate_request request;
173 	struct tegra_bpmp_clk_message msg;
174 	int err;
175 
176 	memset(&request, 0, sizeof(request));
177 	request.rate = rate;
178 
179 	memset(&msg, 0, sizeof(msg));
180 	msg.cmd = CMD_CLK_ROUND_RATE;
181 	msg.id = clk->id;
182 	msg.tx.data = &request;
183 	msg.tx.size = sizeof(request);
184 	msg.rx.data = &response;
185 	msg.rx.size = sizeof(response);
186 
187 	err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
188 	if (err < 0)
189 		return err;
190 
191 	return response.rate;
192 }
193 
194 static int tegra_bpmp_clk_set_parent(struct clk_hw *hw, u8 index)
195 {
196 	struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
197 	struct cmd_clk_set_parent_response response;
198 	struct cmd_clk_set_parent_request request;
199 	struct tegra_bpmp_clk_message msg;
200 	int err;
201 
202 	memset(&request, 0, sizeof(request));
203 	request.parent_id = clk->parents[index];
204 
205 	memset(&msg, 0, sizeof(msg));
206 	msg.cmd = CMD_CLK_SET_PARENT;
207 	msg.id = clk->id;
208 	msg.tx.data = &request;
209 	msg.tx.size = sizeof(request);
210 	msg.rx.data = &response;
211 	msg.rx.size = sizeof(response);
212 
213 	err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
214 	if (err < 0)
215 		return err;
216 
217 	/* XXX check parent ID in response */
218 
219 	return 0;
220 }
221 
222 static u8 tegra_bpmp_clk_get_parent(struct clk_hw *hw)
223 {
224 	struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
225 	struct cmd_clk_get_parent_response response;
226 	struct tegra_bpmp_clk_message msg;
227 	unsigned int i;
228 	int err;
229 
230 	memset(&msg, 0, sizeof(msg));
231 	msg.cmd = CMD_CLK_GET_PARENT;
232 	msg.id = clk->id;
233 	msg.rx.data = &response;
234 	msg.rx.size = sizeof(response);
235 
236 	err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
237 	if (err < 0) {
238 		dev_err(clk->bpmp->dev, "failed to get parent for %s: %d\n",
239 			clk_hw_get_name(hw), err);
240 		return U8_MAX;
241 	}
242 
243 	for (i = 0; i < clk->num_parents; i++)
244 		if (clk->parents[i] == response.parent_id)
245 			return i;
246 
247 	return U8_MAX;
248 }
249 
250 static int tegra_bpmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
251 				   unsigned long parent_rate)
252 {
253 	struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
254 	struct cmd_clk_set_rate_response response;
255 	struct cmd_clk_set_rate_request request;
256 	struct tegra_bpmp_clk_message msg;
257 
258 	memset(&request, 0, sizeof(request));
259 	request.rate = rate;
260 
261 	memset(&msg, 0, sizeof(msg));
262 	msg.cmd = CMD_CLK_SET_RATE;
263 	msg.id = clk->id;
264 	msg.tx.data = &request;
265 	msg.tx.size = sizeof(request);
266 	msg.rx.data = &response;
267 	msg.rx.size = sizeof(response);
268 
269 	return tegra_bpmp_clk_transfer(clk->bpmp, &msg);
270 }
271 
272 static const struct clk_ops tegra_bpmp_clk_gate_ops = {
273 	.prepare = tegra_bpmp_clk_prepare,
274 	.unprepare = tegra_bpmp_clk_unprepare,
275 	.is_prepared = tegra_bpmp_clk_is_prepared,
276 	.recalc_rate = tegra_bpmp_clk_recalc_rate,
277 };
278 
279 static const struct clk_ops tegra_bpmp_clk_mux_ops = {
280 	.prepare = tegra_bpmp_clk_prepare,
281 	.unprepare = tegra_bpmp_clk_unprepare,
282 	.is_prepared = tegra_bpmp_clk_is_prepared,
283 	.recalc_rate = tegra_bpmp_clk_recalc_rate,
284 	.set_parent = tegra_bpmp_clk_set_parent,
285 	.get_parent = tegra_bpmp_clk_get_parent,
286 };
287 
288 static const struct clk_ops tegra_bpmp_clk_rate_ops = {
289 	.prepare = tegra_bpmp_clk_prepare,
290 	.unprepare = tegra_bpmp_clk_unprepare,
291 	.is_prepared = tegra_bpmp_clk_is_prepared,
292 	.recalc_rate = tegra_bpmp_clk_recalc_rate,
293 	.round_rate = tegra_bpmp_clk_round_rate,
294 	.set_rate = tegra_bpmp_clk_set_rate,
295 };
296 
297 static const struct clk_ops tegra_bpmp_clk_mux_rate_ops = {
298 	.prepare = tegra_bpmp_clk_prepare,
299 	.unprepare = tegra_bpmp_clk_unprepare,
300 	.is_prepared = tegra_bpmp_clk_is_prepared,
301 	.recalc_rate = tegra_bpmp_clk_recalc_rate,
302 	.round_rate = tegra_bpmp_clk_round_rate,
303 	.set_parent = tegra_bpmp_clk_set_parent,
304 	.get_parent = tegra_bpmp_clk_get_parent,
305 	.set_rate = tegra_bpmp_clk_set_rate,
306 };
307 
308 static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp *bpmp)
309 {
310 	struct cmd_clk_get_max_clk_id_response response;
311 	struct tegra_bpmp_clk_message msg;
312 	int err;
313 
314 	memset(&msg, 0, sizeof(msg));
315 	msg.cmd = CMD_CLK_GET_MAX_CLK_ID;
316 	msg.rx.data = &response;
317 	msg.rx.size = sizeof(response);
318 
319 	err = tegra_bpmp_clk_transfer(bpmp, &msg);
320 	if (err < 0)
321 		return err;
322 
323 	if (response.max_id > INT_MAX)
324 		return -E2BIG;
325 
326 	return response.max_id;
327 }
328 
329 static int tegra_bpmp_clk_get_info(struct tegra_bpmp *bpmp, unsigned int id,
330 				   struct tegra_bpmp_clk_info *info)
331 {
332 	struct cmd_clk_get_all_info_response response;
333 	struct tegra_bpmp_clk_message msg;
334 	unsigned int i;
335 	int err;
336 
337 	memset(&msg, 0, sizeof(msg));
338 	msg.cmd = CMD_CLK_GET_ALL_INFO;
339 	msg.id = id;
340 	msg.rx.data = &response;
341 	msg.rx.size = sizeof(response);
342 
343 	err = tegra_bpmp_clk_transfer(bpmp, &msg);
344 	if (err < 0)
345 		return err;
346 
347 	strlcpy(info->name, response.name, MRQ_CLK_NAME_MAXLEN);
348 	info->num_parents = response.num_parents;
349 
350 	for (i = 0; i < info->num_parents; i++)
351 		info->parents[i] = response.parents[i];
352 
353 	info->flags = response.flags;
354 
355 	return 0;
356 }
357 
358 static void tegra_bpmp_clk_info_dump(struct tegra_bpmp *bpmp,
359 				     const char *level,
360 				     const struct tegra_bpmp_clk_info *info)
361 {
362 	const char *prefix = "";
363 	struct seq_buf buf;
364 	unsigned int i;
365 	char flags[64];
366 
367 	seq_buf_init(&buf, flags, sizeof(flags));
368 
369 	if (info->flags)
370 		seq_buf_printf(&buf, "(");
371 
372 	if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
373 		seq_buf_printf(&buf, "%smux", prefix);
374 		prefix = ", ";
375 	}
376 
377 	if ((info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE) == 0) {
378 		seq_buf_printf(&buf, "%sfixed", prefix);
379 		prefix = ", ";
380 	}
381 
382 	if (info->flags & TEGRA_BPMP_CLK_IS_ROOT) {
383 		seq_buf_printf(&buf, "%sroot", prefix);
384 		prefix = ", ";
385 	}
386 
387 	if (info->flags)
388 		seq_buf_printf(&buf, ")");
389 
390 	dev_printk(level, bpmp->dev, "%03u: %s\n", info->id, info->name);
391 	dev_printk(level, bpmp->dev, "  flags: %lx %s\n", info->flags, flags);
392 	dev_printk(level, bpmp->dev, "  parents: %u\n", info->num_parents);
393 
394 	for (i = 0; i < info->num_parents; i++)
395 		dev_printk(level, bpmp->dev, "    %03u\n", info->parents[i]);
396 }
397 
398 static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp,
399 				   struct tegra_bpmp_clk_info **clocksp)
400 {
401 	struct tegra_bpmp_clk_info *clocks;
402 	unsigned int max_id, id, count = 0;
403 	unsigned int holes = 0;
404 	int err;
405 
406 	err = tegra_bpmp_clk_get_max_id(bpmp);
407 	if (err < 0)
408 		return err;
409 
410 	max_id = err;
411 
412 	dev_dbg(bpmp->dev, "maximum clock ID: %u\n", max_id);
413 
414 	clocks = kcalloc(max_id + 1, sizeof(*clocks), GFP_KERNEL);
415 	if (!clocks)
416 		return -ENOMEM;
417 
418 	for (id = 0; id <= max_id; id++) {
419 		struct tegra_bpmp_clk_info *info = &clocks[count];
420 
421 		err = tegra_bpmp_clk_get_info(bpmp, id, info);
422 		if (err < 0)
423 			continue;
424 
425 		if (info->num_parents >= U8_MAX) {
426 			dev_err(bpmp->dev,
427 				"clock %u has too many parents (%u, max: %u)\n",
428 				id, info->num_parents, U8_MAX);
429 			continue;
430 		}
431 
432 		/* clock not exposed by BPMP */
433 		if (info->name[0] == '\0') {
434 			holes++;
435 			continue;
436 		}
437 
438 		info->id = id;
439 		count++;
440 
441 		if (TEGRA_BPMP_DUMP_CLOCK_INFO)
442 			tegra_bpmp_clk_info_dump(bpmp, KERN_DEBUG, info);
443 	}
444 
445 	dev_dbg(bpmp->dev, "holes: %u\n", holes);
446 	*clocksp = clocks;
447 
448 	return count;
449 }
450 
451 static const struct tegra_bpmp_clk_info *
452 tegra_bpmp_clk_find(const struct tegra_bpmp_clk_info *clocks,
453 		    unsigned int num_clocks, unsigned int id)
454 {
455 	unsigned int i;
456 
457 	for (i = 0; i < num_clocks; i++)
458 		if (clocks[i].id == id)
459 			return &clocks[i];
460 
461 	return NULL;
462 }
463 
464 static struct tegra_bpmp_clk *
465 tegra_bpmp_clk_register(struct tegra_bpmp *bpmp,
466 			const struct tegra_bpmp_clk_info *info,
467 			const struct tegra_bpmp_clk_info *clocks,
468 			unsigned int num_clocks)
469 {
470 	struct tegra_bpmp_clk *clk;
471 	struct clk_init_data init;
472 	const char **parents;
473 	unsigned int i;
474 	int err;
475 
476 	clk = devm_kzalloc(bpmp->dev, sizeof(*clk), GFP_KERNEL);
477 	if (!clk)
478 		return ERR_PTR(-ENOMEM);
479 
480 	clk->id = info->id;
481 	clk->bpmp = bpmp;
482 
483 	clk->parents = devm_kcalloc(bpmp->dev, info->num_parents,
484 				    sizeof(*clk->parents), GFP_KERNEL);
485 	if (!clk->parents)
486 		return ERR_PTR(-ENOMEM);
487 
488 	clk->num_parents = info->num_parents;
489 
490 	/* hardware clock initialization */
491 	memset(&init, 0, sizeof(init));
492 	init.name = info->name;
493 	clk->hw.init = &init;
494 
495 	if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
496 		if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE)
497 			init.ops = &tegra_bpmp_clk_mux_rate_ops;
498 		else
499 			init.ops = &tegra_bpmp_clk_mux_ops;
500 	} else {
501 		if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE)
502 			init.ops = &tegra_bpmp_clk_rate_ops;
503 		else
504 			init.ops = &tegra_bpmp_clk_gate_ops;
505 	}
506 
507 	init.num_parents = info->num_parents;
508 
509 	parents = kcalloc(info->num_parents, sizeof(*parents), GFP_KERNEL);
510 	if (!parents)
511 		return ERR_PTR(-ENOMEM);
512 
513 	for (i = 0; i < info->num_parents; i++) {
514 		const struct tegra_bpmp_clk_info *parent;
515 
516 		/* keep a private copy of the ID to parent index map */
517 		clk->parents[i] = info->parents[i];
518 
519 		parent = tegra_bpmp_clk_find(clocks, num_clocks,
520 					     info->parents[i]);
521 		if (!parent) {
522 			dev_err(bpmp->dev, "no parent %u found for %u\n",
523 				info->parents[i], info->id);
524 			continue;
525 		}
526 
527 		parents[i] = parent->name;
528 	}
529 
530 	init.parent_names = parents;
531 
532 	err = devm_clk_hw_register(bpmp->dev, &clk->hw);
533 
534 	kfree(parents);
535 
536 	if (err < 0)
537 		return ERR_PTR(err);
538 
539 	return clk;
540 }
541 
542 static int tegra_bpmp_register_clocks(struct tegra_bpmp *bpmp,
543 				      struct tegra_bpmp_clk_info *infos,
544 				      unsigned int count)
545 {
546 	struct tegra_bpmp_clk *clk;
547 	unsigned int i;
548 
549 	bpmp->num_clocks = count;
550 
551 	bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(clk), GFP_KERNEL);
552 	if (!bpmp->clocks)
553 		return -ENOMEM;
554 
555 	for (i = 0; i < count; i++) {
556 		struct tegra_bpmp_clk_info *info = &infos[i];
557 
558 		clk = tegra_bpmp_clk_register(bpmp, info, infos, count);
559 		if (IS_ERR(clk)) {
560 			dev_err(bpmp->dev,
561 				"failed to register clock %u (%s): %ld\n",
562 				info->id, info->name, PTR_ERR(clk));
563 			continue;
564 		}
565 
566 		bpmp->clocks[i] = clk;
567 	}
568 
569 	return 0;
570 }
571 
572 static void tegra_bpmp_unregister_clocks(struct tegra_bpmp *bpmp)
573 {
574 	unsigned int i;
575 
576 	for (i = 0; i < bpmp->num_clocks; i++)
577 		clk_hw_unregister(&bpmp->clocks[i]->hw);
578 }
579 
580 static struct clk_hw *tegra_bpmp_clk_of_xlate(struct of_phandle_args *clkspec,
581 					      void *data)
582 {
583 	unsigned int id = clkspec->args[0], i;
584 	struct tegra_bpmp *bpmp = data;
585 
586 	for (i = 0; i < bpmp->num_clocks; i++) {
587 		struct tegra_bpmp_clk *clk = bpmp->clocks[i];
588 
589 		if (!clk)
590 			continue;
591 
592 		if (clk->id == id)
593 			return &clk->hw;
594 	}
595 
596 	return NULL;
597 }
598 
599 int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp)
600 {
601 	struct tegra_bpmp_clk_info *clocks;
602 	unsigned int count;
603 	int err;
604 
605 	err = tegra_bpmp_probe_clocks(bpmp, &clocks);
606 	if (err < 0)
607 		return err;
608 
609 	count = err;
610 
611 	dev_dbg(bpmp->dev, "%u clocks probed\n", count);
612 
613 	err = tegra_bpmp_register_clocks(bpmp, clocks, count);
614 	if (err < 0)
615 		goto free;
616 
617 	err = of_clk_add_hw_provider(bpmp->dev->of_node,
618 				     tegra_bpmp_clk_of_xlate,
619 				     bpmp);
620 	if (err < 0) {
621 		tegra_bpmp_unregister_clocks(bpmp);
622 		goto free;
623 	}
624 
625 free:
626 	kfree(clocks);
627 	return err;
628 }
629