1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2016-2020 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 long tegra_bpmp_clk_round_rate(struct clk_hw
*hw
, unsigned long rate
,
168 unsigned long *parent_rate
)
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
;
176 memset(&request
, 0, sizeof(request
));
177 request
.rate
= min_t(u64
, rate
, S64_MAX
);
179 memset(&msg
, 0, sizeof(msg
));
180 msg
.cmd
= CMD_CLK_ROUND_RATE
;
182 msg
.tx
.data
= &request
;
183 msg
.tx
.size
= sizeof(request
);
184 msg
.rx
.data
= &response
;
185 msg
.rx
.size
= sizeof(response
);
187 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
191 return response
.rate
;
194 static int tegra_bpmp_clk_set_parent(struct clk_hw
*hw
, u8 index
)
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
;
202 memset(&request
, 0, sizeof(request
));
203 request
.parent_id
= clk
->parents
[index
];
205 memset(&msg
, 0, sizeof(msg
));
206 msg
.cmd
= CMD_CLK_SET_PARENT
;
208 msg
.tx
.data
= &request
;
209 msg
.tx
.size
= sizeof(request
);
210 msg
.rx
.data
= &response
;
211 msg
.rx
.size
= sizeof(response
);
213 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
217 /* XXX check parent ID in response */
222 static u8
tegra_bpmp_clk_get_parent(struct clk_hw
*hw
)
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
;
230 memset(&msg
, 0, sizeof(msg
));
231 msg
.cmd
= CMD_CLK_GET_PARENT
;
233 msg
.rx
.data
= &response
;
234 msg
.rx
.size
= sizeof(response
);
236 err
= tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
238 dev_err(clk
->bpmp
->dev
, "failed to get parent for %s: %d\n",
239 clk_hw_get_name(hw
), err
);
243 for (i
= 0; i
< clk
->num_parents
; i
++)
244 if (clk
->parents
[i
] == response
.parent_id
)
250 static int tegra_bpmp_clk_set_rate(struct clk_hw
*hw
, unsigned long rate
,
251 unsigned long parent_rate
)
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
;
258 memset(&request
, 0, sizeof(request
));
259 request
.rate
= min_t(u64
, rate
, S64_MAX
);
261 memset(&msg
, 0, sizeof(msg
));
262 msg
.cmd
= CMD_CLK_SET_RATE
;
264 msg
.tx
.data
= &request
;
265 msg
.tx
.size
= sizeof(request
);
266 msg
.rx
.data
= &response
;
267 msg
.rx
.size
= sizeof(response
);
269 return tegra_bpmp_clk_transfer(clk
->bpmp
, &msg
);
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
,
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
,
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
,
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
,
308 static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp
*bpmp
)
310 struct cmd_clk_get_max_clk_id_response response
;
311 struct tegra_bpmp_clk_message msg
;
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
);
319 err
= tegra_bpmp_clk_transfer(bpmp
, &msg
);
323 if (response
.max_id
> INT_MAX
)
326 return response
.max_id
;
329 static int tegra_bpmp_clk_get_info(struct tegra_bpmp
*bpmp
, unsigned int id
,
330 struct tegra_bpmp_clk_info
*info
)
332 struct cmd_clk_get_all_info_response response
;
333 struct tegra_bpmp_clk_message msg
;
337 memset(&msg
, 0, sizeof(msg
));
338 msg
.cmd
= CMD_CLK_GET_ALL_INFO
;
340 msg
.rx
.data
= &response
;
341 msg
.rx
.size
= sizeof(response
);
343 err
= tegra_bpmp_clk_transfer(bpmp
, &msg
);
347 strlcpy(info
->name
, response
.name
, MRQ_CLK_NAME_MAXLEN
);
348 info
->num_parents
= response
.num_parents
;
350 for (i
= 0; i
< info
->num_parents
; i
++)
351 info
->parents
[i
] = response
.parents
[i
];
353 info
->flags
= response
.flags
;
358 static void tegra_bpmp_clk_info_dump(struct tegra_bpmp
*bpmp
,
360 const struct tegra_bpmp_clk_info
*info
)
362 const char *prefix
= "";
367 seq_buf_init(&buf
, flags
, sizeof(flags
));
370 seq_buf_printf(&buf
, "(");
372 if (info
->flags
& TEGRA_BPMP_CLK_HAS_MUX
) {
373 seq_buf_printf(&buf
, "%smux", prefix
);
377 if ((info
->flags
& TEGRA_BPMP_CLK_HAS_SET_RATE
) == 0) {
378 seq_buf_printf(&buf
, "%sfixed", prefix
);
382 if (info
->flags
& TEGRA_BPMP_CLK_IS_ROOT
) {
383 seq_buf_printf(&buf
, "%sroot", prefix
);
388 seq_buf_printf(&buf
, ")");
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
);
394 for (i
= 0; i
< info
->num_parents
; i
++)
395 dev_printk(level
, bpmp
->dev
, " %03u\n", info
->parents
[i
]);
398 static int tegra_bpmp_probe_clocks(struct tegra_bpmp
*bpmp
,
399 struct tegra_bpmp_clk_info
**clocksp
)
401 struct tegra_bpmp_clk_info
*clocks
;
402 unsigned int max_id
, id
, count
= 0;
403 unsigned int holes
= 0;
406 err
= tegra_bpmp_clk_get_max_id(bpmp
);
412 dev_dbg(bpmp
->dev
, "maximum clock ID: %u\n", max_id
);
414 clocks
= kcalloc(max_id
+ 1, sizeof(*clocks
), GFP_KERNEL
);
418 for (id
= 0; id
<= max_id
; id
++) {
419 struct tegra_bpmp_clk_info
*info
= &clocks
[count
];
421 err
= tegra_bpmp_clk_get_info(bpmp
, id
, info
);
425 if (info
->num_parents
>= U8_MAX
) {
427 "clock %u has too many parents (%u, max: %u)\n",
428 id
, info
->num_parents
, U8_MAX
);
432 /* clock not exposed by BPMP */
433 if (info
->name
[0] == '\0') {
441 if (TEGRA_BPMP_DUMP_CLOCK_INFO
)
442 tegra_bpmp_clk_info_dump(bpmp
, KERN_DEBUG
, info
);
445 dev_dbg(bpmp
->dev
, "holes: %u\n", holes
);
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
)
457 for (i
= 0; i
< num_clocks
; i
++)
458 if (clocks
[i
].id
== id
)
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
)
470 struct tegra_bpmp_clk
*clk
;
471 struct clk_init_data init
;
472 const char **parents
;
476 clk
= devm_kzalloc(bpmp
->dev
, sizeof(*clk
), GFP_KERNEL
);
478 return ERR_PTR(-ENOMEM
);
483 clk
->parents
= devm_kcalloc(bpmp
->dev
, info
->num_parents
,
484 sizeof(*clk
->parents
), GFP_KERNEL
);
486 return ERR_PTR(-ENOMEM
);
488 clk
->num_parents
= info
->num_parents
;
490 /* hardware clock initialization */
491 memset(&init
, 0, sizeof(init
));
492 init
.name
= info
->name
;
493 clk
->hw
.init
= &init
;
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
;
499 init
.ops
= &tegra_bpmp_clk_mux_ops
;
501 if (info
->flags
& TEGRA_BPMP_CLK_HAS_SET_RATE
)
502 init
.ops
= &tegra_bpmp_clk_rate_ops
;
504 init
.ops
= &tegra_bpmp_clk_gate_ops
;
507 init
.num_parents
= info
->num_parents
;
509 parents
= kcalloc(info
->num_parents
, sizeof(*parents
), GFP_KERNEL
);
511 return ERR_PTR(-ENOMEM
);
513 for (i
= 0; i
< info
->num_parents
; i
++) {
514 const struct tegra_bpmp_clk_info
*parent
;
516 /* keep a private copy of the ID to parent index map */
517 clk
->parents
[i
] = info
->parents
[i
];
519 parent
= tegra_bpmp_clk_find(clocks
, num_clocks
,
522 dev_err(bpmp
->dev
, "no parent %u found for %u\n",
523 info
->parents
[i
], info
->id
);
527 parents
[i
] = parent
->name
;
530 init
.parent_names
= parents
;
532 err
= devm_clk_hw_register(bpmp
->dev
, &clk
->hw
);
542 static int tegra_bpmp_register_clocks(struct tegra_bpmp
*bpmp
,
543 struct tegra_bpmp_clk_info
*infos
,
546 struct tegra_bpmp_clk
*clk
;
549 bpmp
->num_clocks
= count
;
551 bpmp
->clocks
= devm_kcalloc(bpmp
->dev
, count
, sizeof(clk
), GFP_KERNEL
);
555 for (i
= 0; i
< count
; i
++) {
556 struct tegra_bpmp_clk_info
*info
= &infos
[i
];
558 clk
= tegra_bpmp_clk_register(bpmp
, info
, infos
, count
);
561 "failed to register clock %u (%s): %ld\n",
562 info
->id
, info
->name
, PTR_ERR(clk
));
566 bpmp
->clocks
[i
] = clk
;
572 static void tegra_bpmp_unregister_clocks(struct tegra_bpmp
*bpmp
)
576 for (i
= 0; i
< bpmp
->num_clocks
; i
++)
577 clk_hw_unregister(&bpmp
->clocks
[i
]->hw
);
580 static struct clk_hw
*tegra_bpmp_clk_of_xlate(struct of_phandle_args
*clkspec
,
583 unsigned int id
= clkspec
->args
[0], i
;
584 struct tegra_bpmp
*bpmp
= data
;
586 for (i
= 0; i
< bpmp
->num_clocks
; i
++) {
587 struct tegra_bpmp_clk
*clk
= bpmp
->clocks
[i
];
599 int tegra_bpmp_init_clocks(struct tegra_bpmp
*bpmp
)
601 struct tegra_bpmp_clk_info
*clocks
;
605 err
= tegra_bpmp_probe_clocks(bpmp
, &clocks
);
611 dev_dbg(bpmp
->dev
, "%u clocks probed\n", count
);
613 err
= tegra_bpmp_register_clocks(bpmp
, clocks
, count
);
617 err
= of_clk_add_hw_provider(bpmp
->dev
->of_node
,
618 tegra_bpmp_clk_of_xlate
,
621 tegra_bpmp_unregister_clocks(bpmp
);