1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2016-2022 NVIDIA Corporation
6 #include <linux/clk-provider.h>
7 #include <linux/device.h>
8 #include <linux/seq_buf.h>
9 #include <linux/slab.h>
11 #include <soc/tegra/bpmp.h>
12 #include <soc/tegra/bpmp-abi.h>
14 #define TEGRA_BPMP_DUMP_CLOCK_INFO 0
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)
20 struct tegra_bpmp_clk_info
{
22 char name
[MRQ_CLK_NAME_MAXLEN
];
23 unsigned int parents
[MRQ_CLK_MAX_PARENTS
];
24 unsigned int num_parents
;
28 struct tegra_bpmp_clk
{
31 struct tegra_bpmp
*bpmp
;
34 unsigned int num_parents
;
35 unsigned int *parents
;
38 static inline struct tegra_bpmp_clk
*to_tegra_bpmp_clk(struct clk_hw
*hw
)
40 return container_of(hw
, struct tegra_bpmp_clk
, hw
);
43 struct tegra_bpmp_clk_message
{
59 static int tegra_bpmp_clk_transfer(struct tegra_bpmp
*bpmp
,
60 const struct tegra_bpmp_clk_message
*clk
)
62 struct mrq_clk_request request
;
63 struct tegra_bpmp_message msg
;
67 memset(&request
, 0, sizeof(request
));
68 request
.cmd_and_id
= (clk
->cmd
<< 24) | clk
->id
;
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
77 memcpy(req
+ 4, clk
->tx
.data
, clk
->tx
.size
);
79 memset(&msg
, 0, sizeof(msg
));
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
;
86 err
= tegra_bpmp_transfer(bpmp
, &msg
);
89 else if (msg
.rx
.ret
< 0)
95 static int tegra_bpmp_clk_prepare(struct clk_hw
*hw
)
97 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
98 struct tegra_bpmp_clk_message msg
;
100 memset(&msg
, 0, sizeof(msg
));
101 msg
.cmd
= CMD_CLK_ENABLE
;
104 return tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
107 static void tegra_bpmp_clk_unprepare(struct clk_hw
*hw
)
109 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
110 struct tegra_bpmp_clk_message msg
;
113 memset(&msg
, 0, sizeof(msg
));
114 msg
.cmd
= CMD_CLK_DISABLE
;
117 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
119 dev_err(clk
->bpmp
->dev
, "failed to disable clock %s: %d\n",
120 clk_hw_get_name(hw
), err
);
123 static int tegra_bpmp_clk_is_prepared(struct clk_hw
*hw
)
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
;
130 memset(&msg
, 0, sizeof(msg
));
131 msg
.cmd
= CMD_CLK_IS_ENABLED
;
133 msg
.rx
.data
= &response
;
134 msg
.rx
.size
= sizeof(response
);
136 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
140 return response
.state
;
143 static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw
*hw
,
144 unsigned long parent_rate
)
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
;
152 memset(&msg
, 0, sizeof(msg
));
153 msg
.cmd
= CMD_CLK_GET_RATE
;
155 msg
.tx
.data
= &request
;
156 msg
.tx
.size
= sizeof(request
);
157 msg
.rx
.data
= &response
;
158 msg
.rx
.size
= sizeof(response
);
160 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
164 return response
.rate
;
167 static int tegra_bpmp_clk_determine_rate(struct clk_hw
*hw
,
168 struct clk_rate_request
*rate_req
)
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
;
177 rate
= clamp(rate_req
->rate
, rate_req
->min_rate
, rate_req
->max_rate
);
179 memset(&request
, 0, sizeof(request
));
180 request
.rate
= min_t(u64
, rate
, S64_MAX
);
182 memset(&msg
, 0, sizeof(msg
));
183 msg
.cmd
= CMD_CLK_ROUND_RATE
;
185 msg
.tx
.data
= &request
;
186 msg
.tx
.size
= sizeof(request
);
187 msg
.rx
.data
= &response
;
188 msg
.rx
.size
= sizeof(response
);
190 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
194 rate_req
->rate
= (unsigned long)response
.rate
;
199 static int tegra_bpmp_clk_set_parent(struct clk_hw
*hw
, u8 index
)
201 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
202 struct cmd_clk_set_parent_response response
;
203 struct cmd_clk_set_parent_request request
;
204 struct tegra_bpmp_clk_message msg
;
207 memset(&request
, 0, sizeof(request
));
208 request
.parent_id
= clk
->parents
[index
];
210 memset(&msg
, 0, sizeof(msg
));
211 msg
.cmd
= CMD_CLK_SET_PARENT
;
213 msg
.tx
.data
= &request
;
214 msg
.tx
.size
= sizeof(request
);
215 msg
.rx
.data
= &response
;
216 msg
.rx
.size
= sizeof(response
);
218 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
222 /* XXX check parent ID in response */
227 static u8
tegra_bpmp_clk_get_parent(struct clk_hw
*hw
)
229 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
230 struct cmd_clk_get_parent_response response
;
231 struct tegra_bpmp_clk_message msg
;
235 memset(&msg
, 0, sizeof(msg
));
236 msg
.cmd
= CMD_CLK_GET_PARENT
;
238 msg
.rx
.data
= &response
;
239 msg
.rx
.size
= sizeof(response
);
241 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
243 dev_err(clk
->bpmp
->dev
, "failed to get parent for %s: %d\n",
244 clk_hw_get_name(hw
), err
);
248 for (i
= 0; i
< clk
->num_parents
; i
++)
249 if (clk
->parents
[i
] == response
.parent_id
)
255 static int tegra_bpmp_clk_set_rate(struct clk_hw
*hw
, unsigned long rate
,
256 unsigned long parent_rate
)
258 struct tegra_bpmp_clk
*clk
= to_tegra_bpmp_clk(hw
);
259 struct cmd_clk_set_rate_response response
;
260 struct cmd_clk_set_rate_request request
;
261 struct tegra_bpmp_clk_message msg
;
263 memset(&request
, 0, sizeof(request
));
264 request
.rate
= min_t(u64
, rate
, S64_MAX
);
266 memset(&msg
, 0, sizeof(msg
));
267 msg
.cmd
= CMD_CLK_SET_RATE
;
269 msg
.tx
.data
= &request
;
270 msg
.tx
.size
= sizeof(request
);
271 msg
.rx
.data
= &response
;
272 msg
.rx
.size
= sizeof(response
);
274 return tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
277 static const struct clk_ops tegra_bpmp_clk_gate_ops
= {
278 .prepare
= tegra_bpmp_clk_prepare
,
279 .unprepare
= tegra_bpmp_clk_unprepare
,
280 .is_prepared
= tegra_bpmp_clk_is_prepared
,
281 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
284 static const struct clk_ops tegra_bpmp_clk_mux_ops
= {
285 .prepare
= tegra_bpmp_clk_prepare
,
286 .unprepare
= tegra_bpmp_clk_unprepare
,
287 .is_prepared
= tegra_bpmp_clk_is_prepared
,
288 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
289 .determine_rate
= clk_hw_determine_rate_no_reparent
,
290 .set_parent
= tegra_bpmp_clk_set_parent
,
291 .get_parent
= tegra_bpmp_clk_get_parent
,
294 static const struct clk_ops tegra_bpmp_clk_rate_ops
= {
295 .prepare
= tegra_bpmp_clk_prepare
,
296 .unprepare
= tegra_bpmp_clk_unprepare
,
297 .is_prepared
= tegra_bpmp_clk_is_prepared
,
298 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
299 .determine_rate
= tegra_bpmp_clk_determine_rate
,
300 .set_rate
= tegra_bpmp_clk_set_rate
,
303 static const struct clk_ops tegra_bpmp_clk_mux_rate_ops
= {
304 .prepare
= tegra_bpmp_clk_prepare
,
305 .unprepare
= tegra_bpmp_clk_unprepare
,
306 .is_prepared
= tegra_bpmp_clk_is_prepared
,
307 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
308 .determine_rate
= tegra_bpmp_clk_determine_rate
,
309 .set_parent
= tegra_bpmp_clk_set_parent
,
310 .get_parent
= tegra_bpmp_clk_get_parent
,
311 .set_rate
= tegra_bpmp_clk_set_rate
,
314 static const struct clk_ops tegra_bpmp_clk_mux_read_only_ops
= {
315 .get_parent
= tegra_bpmp_clk_get_parent
,
316 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
319 static const struct clk_ops tegra_bpmp_clk_read_only_ops
= {
320 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
323 static const struct clk_ops tegra_bpmp_clk_gate_mux_read_only_ops
= {
324 .prepare
= tegra_bpmp_clk_prepare
,
325 .unprepare
= tegra_bpmp_clk_unprepare
,
326 .is_prepared
= tegra_bpmp_clk_is_prepared
,
327 .recalc_rate
= tegra_bpmp_clk_recalc_rate
,
328 .get_parent
= tegra_bpmp_clk_get_parent
,
331 static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp
*bpmp
)
333 struct cmd_clk_get_max_clk_id_response response
;
334 struct tegra_bpmp_clk_message msg
;
337 memset(&msg
, 0, sizeof(msg
));
338 msg
.cmd
= CMD_CLK_GET_MAX_CLK_ID
;
339 msg
.rx
.data
= &response
;
340 msg
.rx
.size
= sizeof(response
);
342 err
= tegra_bpmp_clk_transfer(bpmp
, &msg
);
346 if (response
.max_id
> INT_MAX
)
349 return response
.max_id
;
352 static int tegra_bpmp_clk_get_info(struct tegra_bpmp
*bpmp
, unsigned int id
,
353 struct tegra_bpmp_clk_info
*info
)
355 struct cmd_clk_get_all_info_response response
;
356 struct tegra_bpmp_clk_message msg
;
360 memset(&msg
, 0, sizeof(msg
));
361 msg
.cmd
= CMD_CLK_GET_ALL_INFO
;
363 msg
.rx
.data
= &response
;
364 msg
.rx
.size
= sizeof(response
);
366 err
= tegra_bpmp_clk_transfer(bpmp
, &msg
);
370 strscpy(info
->name
, response
.name
, MRQ_CLK_NAME_MAXLEN
);
371 info
->num_parents
= response
.num_parents
;
373 for (i
= 0; i
< info
->num_parents
; i
++)
374 info
->parents
[i
] = response
.parents
[i
];
376 info
->flags
= response
.flags
;
381 static void tegra_bpmp_clk_info_dump(struct tegra_bpmp
*bpmp
,
383 const struct tegra_bpmp_clk_info
*info
)
385 const char *prefix
= "";
390 seq_buf_init(&buf
, flags
, sizeof(flags
));
393 seq_buf_printf(&buf
, "(");
395 if (info
->flags
& TEGRA_BPMP_CLK_HAS_MUX
) {
396 seq_buf_printf(&buf
, "%smux", prefix
);
400 if ((info
->flags
& TEGRA_BPMP_CLK_HAS_SET_RATE
) == 0) {
401 seq_buf_printf(&buf
, "%sfixed", prefix
);
405 if (info
->flags
& TEGRA_BPMP_CLK_IS_ROOT
) {
406 seq_buf_printf(&buf
, "%sroot", prefix
);
411 seq_buf_printf(&buf
, ")");
413 dev_printk(level
, bpmp
->dev
, "%03u: %s\n", info
->id
, info
->name
);
414 dev_printk(level
, bpmp
->dev
, " flags: %lx %s\n", info
->flags
, flags
);
415 dev_printk(level
, bpmp
->dev
, " parents: %u\n", info
->num_parents
);
417 for (i
= 0; i
< info
->num_parents
; i
++)
418 dev_printk(level
, bpmp
->dev
, " %03u\n", info
->parents
[i
]);
421 static int tegra_bpmp_probe_clocks(struct tegra_bpmp
*bpmp
,
422 struct tegra_bpmp_clk_info
**clocksp
)
424 struct tegra_bpmp_clk_info
*clocks
;
425 unsigned int max_id
, id
, count
= 0;
426 unsigned int holes
= 0;
429 err
= tegra_bpmp_clk_get_max_id(bpmp
);
435 dev_dbg(bpmp
->dev
, "maximum clock ID: %u\n", max_id
);
437 clocks
= kcalloc(max_id
+ 1, sizeof(*clocks
), GFP_KERNEL
);
441 for (id
= 0; id
<= max_id
; id
++) {
442 struct tegra_bpmp_clk_info
*info
= &clocks
[count
];
444 err
= tegra_bpmp_clk_get_info(bpmp
, id
, info
);
448 if (info
->num_parents
>= U8_MAX
) {
450 "clock %u has too many parents (%u, max: %u)\n",
451 id
, info
->num_parents
, U8_MAX
);
455 /* clock not exposed by BPMP */
456 if (info
->name
[0] == '\0') {
464 if (TEGRA_BPMP_DUMP_CLOCK_INFO
)
465 tegra_bpmp_clk_info_dump(bpmp
, KERN_DEBUG
, info
);
468 dev_dbg(bpmp
->dev
, "holes: %u\n", holes
);
475 tegra_bpmp_clk_id_to_index(const struct tegra_bpmp_clk_info
*clocks
,
476 unsigned int num_clocks
, unsigned int id
)
480 for (i
= 0; i
< num_clocks
; i
++)
481 if (clocks
[i
].id
== id
)
487 static const struct tegra_bpmp_clk_info
*
488 tegra_bpmp_clk_find(const struct tegra_bpmp_clk_info
*clocks
,
489 unsigned int num_clocks
, unsigned int id
)
493 i
= tegra_bpmp_clk_id_to_index(clocks
, num_clocks
, id
);
501 static struct tegra_bpmp_clk
*
502 tegra_bpmp_clk_register(struct tegra_bpmp
*bpmp
,
503 const struct tegra_bpmp_clk_info
*info
,
504 const struct tegra_bpmp_clk_info
*clocks
,
505 unsigned int num_clocks
)
507 struct tegra_bpmp_clk
*clk
;
508 struct clk_init_data init
;
509 const char **parents
;
513 clk
= devm_kzalloc(bpmp
->dev
, sizeof(*clk
), GFP_KERNEL
);
515 return ERR_PTR(-ENOMEM
);
520 clk
->parents
= devm_kcalloc(bpmp
->dev
, info
->num_parents
,
521 sizeof(*clk
->parents
), GFP_KERNEL
);
523 return ERR_PTR(-ENOMEM
);
525 clk
->num_parents
= info
->num_parents
;
527 /* hardware clock initialization */
528 memset(&init
, 0, sizeof(init
));
529 init
.name
= info
->name
;
530 clk
->hw
.init
= &init
;
531 if (info
->flags
& BPMP_CLK_STATE_CHANGE_DENIED
) {
532 if ((info
->flags
& BPMP_CLK_RATE_PARENT_CHANGE_DENIED
) == 0) {
534 "Firmware bug! Inconsistent permission bits for clock %s. State and parent/rate changes disabled.",
537 if (info
->flags
& TEGRA_BPMP_CLK_HAS_MUX
)
538 init
.ops
= &tegra_bpmp_clk_mux_read_only_ops
;
540 init
.ops
= &tegra_bpmp_clk_read_only_ops
;
541 } else if (info
->flags
& BPMP_CLK_RATE_PARENT_CHANGE_DENIED
) {
542 if (info
->flags
& TEGRA_BPMP_CLK_HAS_MUX
)
543 init
.ops
= &tegra_bpmp_clk_gate_mux_read_only_ops
;
545 init
.ops
= &tegra_bpmp_clk_gate_ops
;
546 } else if (info
->flags
& TEGRA_BPMP_CLK_HAS_MUX
) {
547 if (info
->flags
& TEGRA_BPMP_CLK_HAS_SET_RATE
)
548 init
.ops
= &tegra_bpmp_clk_mux_rate_ops
;
550 init
.ops
= &tegra_bpmp_clk_mux_ops
;
552 if (info
->flags
& TEGRA_BPMP_CLK_HAS_SET_RATE
)
553 init
.ops
= &tegra_bpmp_clk_rate_ops
;
555 init
.ops
= &tegra_bpmp_clk_gate_ops
;
558 init
.num_parents
= info
->num_parents
;
560 parents
= kcalloc(info
->num_parents
, sizeof(*parents
), GFP_KERNEL
);
562 return ERR_PTR(-ENOMEM
);
564 for (i
= 0; i
< info
->num_parents
; i
++) {
565 const struct tegra_bpmp_clk_info
*parent
;
567 /* keep a private copy of the ID to parent index map */
568 clk
->parents
[i
] = info
->parents
[i
];
570 parent
= tegra_bpmp_clk_find(clocks
, num_clocks
,
573 dev_err(bpmp
->dev
, "no parent %u found for %u\n",
574 info
->parents
[i
], info
->id
);
578 parents
[i
] = parent
->name
;
581 init
.parent_names
= parents
;
583 err
= devm_clk_hw_register(bpmp
->dev
, &clk
->hw
);
593 static void tegra_bpmp_register_clocks_one(struct tegra_bpmp
*bpmp
,
594 struct tegra_bpmp_clk_info
*infos
,
599 struct tegra_bpmp_clk_info
*info
;
600 struct tegra_bpmp_clk
*clk
;
602 if (bpmp
->clocks
[i
]) {
603 /* already registered */
608 for (j
= 0; j
< info
->num_parents
; ++j
) {
609 unsigned int p_id
= info
->parents
[j
];
610 unsigned int p_i
= tegra_bpmp_clk_id_to_index(infos
, count
,
613 tegra_bpmp_register_clocks_one(bpmp
, infos
, p_i
, count
);
616 clk
= tegra_bpmp_clk_register(bpmp
, info
, infos
, count
);
619 "failed to register clock %u (%s): %ld\n",
620 info
->id
, info
->name
, PTR_ERR(clk
));
621 /* intentionally store the error pointer to
622 * bpmp->clocks[i] to avoid re-attempting the
627 bpmp
->clocks
[i
] = clk
;
630 static int tegra_bpmp_register_clocks(struct tegra_bpmp
*bpmp
,
631 struct tegra_bpmp_clk_info
*infos
,
636 bpmp
->num_clocks
= count
;
638 bpmp
->clocks
= devm_kcalloc(bpmp
->dev
, count
, sizeof(struct tegra_bpmp_clk
), GFP_KERNEL
);
642 for (i
= 0; i
< count
; i
++) {
643 tegra_bpmp_register_clocks_one(bpmp
, infos
, i
, count
);
649 static void tegra_bpmp_unregister_clocks(struct tegra_bpmp
*bpmp
)
653 for (i
= 0; i
< bpmp
->num_clocks
; i
++)
654 clk_hw_unregister(&bpmp
->clocks
[i
]->hw
);
657 static struct clk_hw
*tegra_bpmp_clk_of_xlate(struct of_phandle_args
*clkspec
,
660 unsigned int id
= clkspec
->args
[0], i
;
661 struct tegra_bpmp
*bpmp
= data
;
663 for (i
= 0; i
< bpmp
->num_clocks
; i
++) {
664 struct tegra_bpmp_clk
*clk
= bpmp
->clocks
[i
];
676 int tegra_bpmp_init_clocks(struct tegra_bpmp
*bpmp
)
678 struct tegra_bpmp_clk_info
*clocks
;
682 err
= tegra_bpmp_probe_clocks(bpmp
, &clocks
);
688 dev_dbg(bpmp
->dev
, "%u clocks probed\n", count
);
690 err
= tegra_bpmp_register_clocks(bpmp
, clocks
, count
);
694 err
= of_clk_add_hw_provider(bpmp
->dev
->of_node
,
695 tegra_bpmp_clk_of_xlate
,
698 tegra_bpmp_unregister_clocks(bpmp
);